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
Uploading multiple image files with Swift
提问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 CRLF
at 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)
}
})
}