xcode 使用 Swift 上传多个图像文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28448837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:38:10  来源:igfitidea点击:

Uploading multiple image files with Swift

iphonexcodeswiftimage-uploadingalamofire

提问by Yrol

Im using the following code to upload a single image to a server (with parameters), However I've been trying to upload multiple images, but could not get it to work

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

Creating NSData objects (of images saved in temp directory). Using netdata class here

创建 NSData 对象(保存在临时目录中的图像)。在这里使用 netdata 类

    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])
    }
}

Using Alamofire to upload

使用 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
}

Generating the Alamofire 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)
}

The parameters array along with the NSData collection as below

参数数组以及 NSData 集合如下

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

"imageData" is a collection of NSData objects of the images. Code works fine but the NSData array of the images received as an empty array. However rest of the parameters including "appversion" and "description" will be received fine

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

回答by Anit Kumar

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
}

Here is Code of Upload Image and Parameters in multipart/form-data

这是 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
   }
}

回答by cnoon

The only thing that looks wrong to me is that you're not creating the initial boundary properly. You should NOT have a CRLFat the beginning of the first boundary. I would try the following instead.

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

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)!)

回答by Gurjit Singh

In SwiftUsing AlamofireJust append "[]" with image upload Param Name to make it array of images. Following is the demo code where I am using "[]" with images upload's param name and creating a loop to same param name. ;-)

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)
                    }

            })
}