【问题标题】:Uploading multiple image files with Swift使用 Swift 上传多个图像文件
【发布时间】:2015-04-11 11:57:57
【问题描述】:

我正在使用以下代码将单个图像上传到服务器(带参数),但是我一直在尝试上传多个图像,但无法正常工作

创建 NSData 对象(保存在临时目录中的图像)。使用网络数据类here

    func uploadData(){
    //create image data objects
    let filemanager:NSFileManager = NSFileManager()
    let files = filemanager.enumeratorAtPath(tempPicPath)
    var counter:Int = Int()
    while let file: AnyObject = files?.nextObject() {
        imagePathCollection.append(tempPicPath + "/" + (file as NSString))
    }

    //convert to data objects ()
    for path in imagePathCollection{
        var image: UIImage? = UIImage(contentsOfFile: path)
        if image != nil {
            var sizeOfImage = image?.size
            var resizedImage = RBSquareImageTo(image!, sizeOfImage!)
            var imageData = UIImageJPEGRepresentation(resizedImage, 75)
            imageDataCollection.append(NetData(data: imageData!, mimeType:MimeType(rawValue: "image/jpeg")!, filename: "myImage.jpeg"))
        }
    }

    if(imageDataCollection.count > 1){
        for (index, element) in enumerate(imageDataCollection) {
            multipleImageUpload(imageDataCollection[index])
        }
    }else{
        singleImageUpload(imageDataCollection[0])
    }
}

使用 Alamofire 上传

        func extrasImageUpoload(urlRequest:(URLRequestConvertible, NSData))->Request{
    let request = Alamofire.upload(urlRequest.0, urlRequest.1)
        .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
            println("progress : \(totalBytesWritten) / \(totalBytesExpectedToWrite)")
    }
    return request
}

生成 Alamofire 请求

    func urlRequestWithComponents(parameters:NSDictionary, uploadType:String) -> (URLRequestConvertible, NSData) {

    var mutableURLRequest:NSMutableURLRequest = NSMutableURLRequest()

    //set url type
    if(uploadType == "extra"){
        mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: baseURL + "ticket/extra")!)
    }else if(uploadType == "checkList"){
        //uploadUrl = "ticket/mark"
        mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: baseURL + "ticket/mark")!)
    }

    // create url request to send
    //var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: baseURL + "ticket/extra")!)
    mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue
    //let boundaryConstant = "myRandomBoundary12345"
    let boundaryConstant = "NET-POST-boundary-\(arc4random())-\(arc4random())"
    let contentType = "multipart/form-data;boundary="+boundaryConstant
    //let pgToken = "c9049df83e8bfd7a3dfaef279cdb74478330ff2a"
    mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")
    mutableURLRequest.setValue(self.token, forHTTPHeaderField: "PG-Auth-Token")

    // create upload data to send
    let uploadData = NSMutableData()

    // add parameters
    for (key, value) in parameters {

        uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

        if value is NetData {
            // add image
            var postData = value as NetData
            //uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(postData.filename)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!
            var filenameClause = " filename=\"\(postData.filename)\""
            let contentDispositionString = "Content-Disposition: form-data; name=\"\(key)\";\(filenameClause)\r\n"
            let contentDispositionData = contentDispositionString.dataUsingEncoding(NSUTF8StringEncoding)
            uploadData.appendData(contentDispositionData!)


            // append content type
            //uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
            let contentTypeString = "Content-Type: \(postData.mimeType.getString())\r\n\r\n"
            let contentTypeData = contentTypeString.dataUsingEncoding(NSUTF8StringEncoding)
            uploadData.appendData(contentTypeData!)
            uploadData.appendData(postData.data)

        }else{
            uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
        }
    }
    uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)

    // return URLRequestConvertible and NSData
    return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData)
}

参数数组以及下面的 NSData 集合

 var params = ["pic":imageData,"ticketid":ticketID, "appversion":Utilities().getAPPVersion(), "description":"bla bla bla", "cost":50]

"imageData" 是图像的 NSData 对象的集合。代码工作正常,但图像的 NSData 数组作为空数组接收。然而,包括“appversion”和“description”在内的其余参数将被正常接收

【问题讨论】:

    标签: iphone xcode swift image-uploading alamofire


    【解决方案1】:
    import MobileCoreServices
    
    
    func createRequest(userid: String, image: [UIImage]) throws -> NSMutableURLRequest {
    
       var parameters: [String : AnyObject] = [
           "userid": userid,
           "Image1": image[0],  // You need to set the UIImage Type image parameters 
           "Image2": image[1],   
           "Image3": image[2],
           "Image4": image[3]
       ]
    
        print(parameters)
    
        let boundary = generateBoundaryString()
    
        let url = URL(string: Your URL String)!
        let request = NSMutableURLRequest(url: url)
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
        request.httpBody = try createBody(with: parameters as [String : AnyObject], boundary: boundary)
    
        return request
    }
    

    这里是multipart/form-data中上传图片和参数的代码

    func createBody(with parameters: [String: AnyObject], boundary: String) throws -> Data {
    
        var body = Data()
    
        for (key, value) in parameters {
    
            if(value is String || value is NSString) {
                body.append("--\(boundary)\r\n")
                body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.append("\(value)\r\n")
            }else if let image = value as? UIImage {
                let r = arc4random()
                let filename = "image\(r).jpg"
                let data = UIImageJPEGRepresentation(image,1);
                let mimetype = mimeTypeForPath(path: filename)
    
                body.append("--\(boundary)\r\n")
                body.append("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n")
                body.append("Content-Type: \(mimetype)\r\n\r\n")
                body.append(data!)
                body.append("\r\n")
            }
    
        }
    
        body.append("--\(boundary)--\r\n")
    
        return body
    
    }
    
    func mimeTypeForPath(path: String) -> String {
        let pathExtension = path.pathExtension
        var stringMimeType = "application/octet-stream";
        if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as! CFString, nil)?.takeRetainedValue() {
            if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
                stringMimeType = mimetype as NSString as String
            }
        }
        return stringMimeType;
    }
    
    extension String {
       var ns: NSString {
           return self as NSString
       }
       var pathExtension: String? {
           return ns.pathExtension
       }
       var lastPathComponent: String? {
           return ns.lastPathComponent
       }
    }
    

    【讨论】:

      【解决方案2】:

      对我来说唯一看起来不对的是您没有正确创建初始边界。您不应该在第一个边界的开头有 CRLF。我会尝试以下方法。

      let uploadData = NSMutableData()
      
      for (index, (key, value)) in enumerate(parameters) {
          if index == 0 {
              uploadData.appendData("--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
          } else {
              uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
          }
      
          if let postData as? NetData {
              var filenameClause = " filename=\"\(postData.filename)\""
              let contentDispositionString = "Content-Disposition: form-data; name=\"\(key)\";\(filenameClause)\r\n"
              let contentDispositionData = contentDispositionString.dataUsingEncoding(NSUTF8StringEncoding)
              uploadData.appendData(contentDispositionData!)
      
              let contentTypeString = "Content-Type: \(postData.mimeType.getString())\r\n\r\n"
              let contentTypeData = contentTypeString.dataUsingEncoding(NSUTF8StringEncoding)
              uploadData.appendData(contentTypeData!)
              uploadData.appendData(postData.data)
          }
      }
      
      uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
      

      【讨论】:

      • 当我尝试进行多重上传时,我得到了这个“快照未渲染的视图会导致空快照。确保您的视图在快照之前或快照之后至少渲染一次屏幕更新。” ".NetData' 没有实现 methodSignatureForSelector: -- 前面的麻烦"
      • 您的快照错误是一个非常不同的问题,与我建议的更改无关。我建议提出一个不同的问题并研究drawViewHierarchyInRect: 方法。至于.NetData 问题,您还没有发布足够的信息继续下去。同样,我不认为这是我发布的代码的问题。
      • 嗨@Yrol,你最终解决了这个问题吗?如果我的回答对您有所帮助,您能否将其标记为优秀的社区用户?干杯。
      • @cnoon 你能检查我的这个问题吗-stackoverflow.com/q/36396575/5395919
      • 嗨@cnoon 很抱歉打扰您,但我发现您的回答可能对我的问题有所帮助。如果您不感兴趣,我理解,但如果您能抽出时间检查一下,我将不胜感激。 stackoverflow.com/questions/40527140/… 还有 50 代表赏金 ;)
      【解决方案3】:

      Swift 中使用 Alamofire 只需在图像上传参数名称后附加“[]”即可使其成为图像数组。以下是演示代码,其中我使用“[]”和图像上传的参数名称并创建一个循环到相同的参数名称。 ;-)

      func uploadImages(withImagesData imagesData: [Foundation.Data], parameters: [String: String]) {
          Alamofire.upload(multipartFormData: { multipartFormData in
                      // import image to request
                      for imageData in imagesData {
                          multipartFormData.append(imageData, withName: "myImageParamName[]", fileName: "\(Date().timeIntervalSince1970).jpeg", mimeType: "image/jpeg")
                      }
                      for (key, value) in parameters {
                          multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
                      }
                  }, to: urlString,
      
                      encodingCompletion: { encodingResult in
                          switch encodingResult {
                          case .success(let upload, _, _):
                              upload.responseJSON { response in
                                  print("upload Success")
                              }
                          case .failure(let error):
                              print("upload Failed With Error: ", error)
                          }
      
                  })
      }
      

      【讨论】:

        猜你喜欢
        • 2020-03-13
        • 1970-01-01
        • 2018-04-02
        • 2015-01-18
        • 1970-01-01
        • 1970-01-01
        • 2020-02-08
        • 2014-02-20
        • 2018-09-16
        相关资源
        最近更新 更多