简体   繁体   中英

Image data shows corrupted or nil when trying to upload to an api with swift

I'm trying to upload an image file from my app to an API for school. When it successfully uploads it just corrupted it cant be preview or it says nil data and only has 1kb of data. I was wondering if there's a problem with my code or something. Also my spring board API says rtException: Required request part 'file' is not present

func use(){
        
        let semaphore = DispatchSemaphore (value: 0)

        let parameters = [
          [
            "key": "file",
            "src": "k.png",
            "type": "file"
          ]] as [[String : Any]]

        let boundary = "Boundary-\(UUID().uuidString)"
        var body = ""
        var _: Error? = nil
        for param in parameters {
          if param["disabled"] == nil {
            let paramName = param["key"]!
            body += "--\(boundary)\r\n"
            body += "Content-Disposition:form-data; name=\"\(paramName)\""
            if param["contentType"] != nil {
              body += "\r\nContent-Type: \(param["contentType"] as! String)"
            }
            let paramType = param["type"] as! String
            if paramType == "text" {
              let paramValue = param["value"] as! String
              body += "\r\n\r\n\(paramValue)\r\n"
            } else {
              let paramSrc = param["src"] as! String
                let fileData = UIImage(data: self.picData)?.pngData()
                let fileContent = String(data: fileData!, encoding: .utf16)
              body += "; filename=\"\(paramSrc)\"\r\n"
                + "Content-Type: \"content-type header\"\r\n\r\n\(String(describing: fileContent))\r\n"
            }
          }
        }
        body += "--\(boundary)--\r\n";
        let postData = body.data(using: .utf16)

        var request = URLRequest(url: URL(string: "cant show my actual url for the project")!,timeoutInterval: Double.infinity)
        request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        request.httpMethod = "POST"
        request.httpBody = postData

        let task = URLSession.shared.dataTask(with: request) { data, response, error in
          guard let data = data else {
            print(String(describing: error))
            semaphore.signal()
            return
          }
          print(String(data: data, encoding: .utf8)!)
          semaphore.signal()
        }

        task.resume()
        semaphore.wait()
        
    }

Stop thinking, and that's a big mistake that a lot of people does, not every Data can be transformed into a String with UTF8 encoding: That's why:

let imageData = UIImage(data: self.picData)?.pngData()
let imageString = String(data: imageData, encoding: .utf8)

Will output a imageString nil , and that's normal.

Now, body should be of type Data , and you append to it Data .

let boundaryString = "Boundary-\(UUID().uuidString)"
let boundaryData = Data("--\(boundaryString)\r\n".utf8)
var body = Data()
for param in parameters {
    if param["disabled"] == nil {
        let paramName = param["key"]!
        body += boundaryData
        body += Data("Content-Disposition:form-data; name=\"\(paramName)\"".utf8)
      if param["contentType"] != nil {
          body += Data("\r\nContent-Type: \(param["contentType"] as! String)".utf8)
      }
      let paramType = param["type"] as! String
      if paramType == "text" {
          let paramValue = param["value"] as! String
          body += Data("\r\n\r\n\(paramValue)\r\n".utf8)
      } else {
          let paramSrc = param["src"] as! String
          let fileData = UIImage(data: self.picData)?.pngData()
          let fileContent = String(data: fileData!, encoding: .utf16)
          body += Data("; filename=\"\(paramSrc)\"\r\n".utf8)
          body += Data("Content-Type: \"content-type header\"\r\n".utf8)
          body += Data("\r\n".utf8)
          body += fileData
          body += Data("\r\n".utf8)
      }
    }
}
body += boundaryData
let postData = body

Now, with proper unwrapping: ie stop using ! :

let boundaryString = "Boundary-\(UUID().uuidString)"
let boundaryData = Data("--\(boundaryString)\r\n".utf8)
var body = Data()
for param in parameters {
    if param["disabled"] == nil, let name = param["key"] as? String {
        body += boundaryData
        body += Data("Content-Disposition:form-data; name=\"\(name)\"".utf8)
        if let contentType = param["contentType"] as? String {
            body += Data("\r\nContent-Type: \(contentType)".utf8)
        }
        if let paramType = param["type"] as? String, 
           paramType == "text", 
           let value = param["value"] as? String {
            body += Data("\r\n\r\n\(value)\r\n".utf8)
        } else if let source = param["src"] as? String, let fileData = UIImage(data: self.picData)?.pngData() {
            let fileContent = String(data: fileData, encoding: .utf16)
            body += Data("; filename=\"\(source)\"\r\n".utf8)
            body += Data("Content-Type: \"content-type header\"\r\n".utf8)
            body += Data("\r\n".utf8)
            body += fileData
            body += Data("\r\n".utf8)
        }
    }
}
body += boundaryData
let postData = body

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM