问题
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
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
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
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
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
回答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
}
Here is Code of Upload Image and Parameters in 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:
The only thing that looks wrong to me is that you're not creating the initial boundary properly. You should NOT have a CRLF
at the beginning of the first boundary. I would try the following instead.
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)!)
回答3:
In Swift Using Alamofire Just 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. ;-)
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)
}
})
}
来源:https://stackoverflow.com/questions/28448837/uploading-multiple-image-files-with-swift