使用Swift上传多个图像文件

时间:2015-02-11 07:32:57

标签: iphone xcode swift image-uploading alamofire

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

创建NSData对象(保存在临时目录中的图像)。使用netdata类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"和"描述"将收到罚款

3 个答案:

答案 0 :(得分:2)

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(value is UIImage) {
            let r = arc4random()
            let filename = "image\(r).jpg"
            let data = UIImageJPEGRepresentation(value as! UIImage,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
   }
}

答案 1 :(得分:1)

对我来说唯一不对的是你没有正确地创建初始边界。你不应该在第一个边界的开头有一个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)!)

答案 2 :(得分:0)

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

            })
}