How to upload the image to amazon bucket in swift3? - ios

I want to post the customer signature image to amazon s3 bucket_type server with an api...I am referring with different tutorials...I didn't get enough information from any of tutorials...I am trying with following code but I am getting nil result...
funcUpload(service:String,imagedata:Data,completion:#escaping (_ result:NSDictionary?,_ error:AnyObject?) -> ()){
let boundaryConstant = "----------V2y2HFg03eptjbaKO0j1"
let urlpath:String = "http:myurl" + service
let url:NSURL = NSURL(string:urlpath)!
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "P0ST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
request.httpShouldHandleCookies = false
let contentType = "multipart/form-data; boundary=\(boundaryConstant)"
request.setValue(contentType, forHTTPHeaderField: "Content-Type"
let body = NSMutableData()
if imagedata != nil{
body.append("--\(boundaryConstant)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\("universalapparealproduct")\" ; filename=\"image.jpg\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \("universalapparealproduct")\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(imagedata)
body.append("\r\n".data(using: String.Encoding.utf8)!)
}
body.append("--\(boundaryConstant)--\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body as Data
let config = URLSessionConfiguration.ephemeral
self.session = URLSession(configuration: config)
let task = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if let receivedData = data
{
do
{let resultDic = try JSONSerialization.jsonObject(with: receivedData, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
completion(resultDic!,nil)
}
catch let error
{
NSLog("\(error)")
}
}
else if let errorMessage = error
{
completion(nil,errorMessage as AnyObject?)
}
self.session.invalidateAndCancel()
}
task.resume()
}
}
Please can any one help me to resolve this issue.
Thanks in advance.

let urlpath:String = "http:myurl" + service looks like a typo.
I assume that the service variable contain a url with pre-signed credentials that you can upload to. Make sure that is correct. If not you have to have a server serve you pre-signed credentials.
use PUT not POST
I would expect that the body of the request would just be the imageData, but you seem to be adding a lot of stuff to body. I don't know what kind of file you want to upload but you are making a weird file. If that is your intent is fine, but just we aware that is what you are doing. If indenting to upload a custom file type, I would move all of that code to a different function and then have another function that just uploads the data.
the only HTTPHeader field that you have to set is Content-Length. It must be set to the size of the body that you send.
The expected result of the request is data with a length of 0 and no error. So your JSONSerialization in the response block in wrong.

func imageUpload(service:String,token:String,imagedata:Data,completion:#escaping (_ result:NSDictionary?,_ error:AnyObject?) -> ())
{
let boundaryConstant = "----------V2y2HFg03eptjbaKO0j1"
let params = NSMutableDictionary()
let bucket_name = "userspecifiedbucketname"
params.setObject("(bucket_name)", forKey:"bucket_type" as NSCopying)
let urlpath:String = "http://\(myurladdress)/" + service
let url:NSURL = NSURL(string:urlpath)!
print("URL:\(url)")
var request = URLRequest(url: url as URL)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
let contentType = "multipart/form-data; boundary=\(boundaryConstant)"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
if token != ""
{
request.setValue("\(token)", forHTTPHeaderField: "Authorization")
}
let body = NSMutableData()
for param in params {
body.append("--\(boundaryConstant)\r\n" .data(using: String.Encoding.utf8,allowLossyConversion: false)! )
body.append("Content-Disposition: form-data; name=\"\(param.key)\"\r\n\r\n" .data(using: String.Encoding.utf8,allowLossyConversion: false)!)
body.append("\(param.value)\r\n" .data(using: String.Encoding.utf8,allowLossyConversion: false)!)
}
body.append("--\(boundaryConstant)\r\n".data(using: String.Encoding.utf8,allowLossyConversion: false)!)
body.append("Content-Disposition: form-data; name=\"\("file")\" ; filename=\"image.jpg\"\r\n".data(using: String.Encoding.utf8,allowLossyConversion: false)!)
body.append("Content-Type: image/jpeg\r\n\r\n".data(using: String.Encoding.utf8,allowLossyConversion: false)!)
body.append(imagedata)
body.append("\r\n".data(using: String.Encoding.utf8,allowLossyConversion: false)!)
// image end
body.append("--\(boundaryConstant)--\r\n".data(using: String.Encoding.utf8,allowLossyConversion: false)!)
request.httpBody = body as Data
let postLength = "\(body.length)"
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
}
NOTE: (Here bucket_name should be same as server side bucket_name )

Related

Server response throwing Unable to process while uploading document/Photo to server in Swift

I am trying to uploading document to server. In Action sheet, User can choose Photo from gallery to Document to upload.
So, I am taking either photo or document and converting it into Data.
After that I am sending that data to server along with two parameters (keys, values) with multipart.
But, Unfortunately I am getting error like Unable to process from server, But same thing working in Android domain.
Here is my code:
func uploadDocument(documentId:Int, data: Data, filePath: String, categoryType: String, completion: #escaping uploadDocumentClosure) {
let url = "https://somedomain.com/uploadDocument"
let requestURL = URL(string: url)!
let request = NSMutableURLRequest(url: requestURL)
request.cachePolicy = .reloadIgnoringLocalCacheData
request.httpShouldHandleCookies = false
request.timeoutInterval = 30
request.httpMethod = "POST"
let filename = "avatar.png"
// generate boundary string using a unique per-app string
let boundary = UUID().uuidString
let docData = data
let idStr = "id"
let docTypeStr = "documentType"
let file = "file"
var data = Data()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.addValue("Bearer \(accessToken ?? "")", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(docTypeStr)\"\r\n\r\n".data(using: .utf8)!)
data.append("\(categoryType)".data(using: .utf8)!)
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(file)\"\r\n\r\n".data(using: .utf8)!)
// Add the image data to the raw http request data
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
// data.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
//
if let dataa = "Content-Disposition: form-data; name=\"\(filename)\"; filename=\"image.jpg\"\r\n".data(using: .utf8) {
data.append(dataa)
}
data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
data.append(docData)
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
self.serviceManager.async(request: request as URLRequest) { (innerClosure) in
do {
let response = try innerClosure()
guard let json = response.jsonObject else {
completion({ throw JSONErrorType.parsingError })
return
}
let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
let responseModel = try JSONDecoder().decode(EditProfilePhotoUploadResponse.self, from: jsonData)
completion({ return responseModel })
} catch {
completion({ throw error })
}
}
}
And the sever response is below
{
"status" : "E",
"message" : "Unable to process.",
"data" : null,
"messageList" : null
}
With status code 400 bad request.
In Android they simply sending below code and its working fine.
#Multipart
#POST("somedomain.com/uploadDocument")
suspend fun uploadDocument(
#Part file: MultipartBody.Part,
#Query("documentType") documentType: String
): GenericMessageResponse
Any suggestions?
After much debugging, I have fixed the issue with below solution.
I used below library
https://github.com/Fyrts/Multipart.git
Here my code changes are below
func uploadDocument(imageData: Data, filePath: String, fileName: String, categoryType: String, completion: #escaping uploadDocumentClosure) {
let url = "https://wwww.somedomain.com/uploadDocument"
let requestURL = URL(string: url)!
let imageeData = ImageData(name: fileName, filePath: filePath, imagedata: imageData)
let string = imageeData.filePath
let mimeType = string.mimeType() //here list of mimes we can get from predefined
let fileContents = try! Data(contentsOf: URL(string: filePath)!)
var message = Multipart(type: .formData)
message.append(Part.FormData(name: "documentType", value: "\(categoryType)"))
message.append(Part.FormData(name: "file", fileData: fileContents, fileName: "\(imageeData.name)", contentType: "\(mimeType)"))
var URLrequest = URLRequest(url: requestURL)
URLrequest.httpMethod = "POST"
URLrequest.setMultipartBody(message)
URLrequest.addValue("/(token)", forHTTPHeaderField: "Authorization")
self.serviceManager.async(request: URLrequest as URLRequest) { (innerClosure) in
do {
let response = try innerClosure()
guard let json = response.jsonObject else {
completion({ throw JSONErrorType.parsingError })
return
}
let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
let responseModel = try JSONDecoder().decode(EditProfilePhotoUploadResponse.self, from: jsonData)
completion({ return responseModel })
} catch {
completion({ throw error })
}
}
}

Required request part 'file' is not present error in Swift

I am trying to upload profile image to server using multipart file upload.
My code is
func uploadPhoto(image: UIImage, filePath: String, completion: #escaping uploadPhotoClosure) {
let imageData = image.jpegData(compressionQuality: 0.3)
let url = "https:www.somepath.com/uploadFile"
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
let boundary = UUID().uuidString
let contentType = "multipart/form-data; boundary=\(boundary)"
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var body = Data()
body.append("\r\n--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("field_mobileinfo_image".data(using: String.Encoding.utf8, allowLossyConversion: true)!)
body.append("\r\n--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"files[field_mobileinfo_image]\"; filename=\"img.jpg\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: application/octet-stream\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(imageData!)
body.append("\r\n--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body
self.serviceManager.async(request: request) { (innerClosure) in
do {
let response = try innerClosure()
guard let json = response.jsonObject else {
completion({ throw JSONErrorType.parsingError })
return
}
let jsonData = try JSONSerialization.data(withJSONObject: json, options: [])
let responseModel = try JSONDecoder().decode(EditProfilePhotoUploadResponse.self, from: jsonData)
completion({ return responseModel })
} catch {
completion({ throw error })
}
}
}
//servicemanager class
func async(request: URLRequest, completion: #escaping ServiceManagerAsyncCompletion) {
ServiceManager.log(request)
let task = self.urlSession.dataTask(with: request) { (data, response, error) in
guard error == nil else {
DispatchQueue.main.async {
completion({ throw error! })
}
return
}
guard let response = response as? HTTPURLResponse else {
DispatchQueue.main.async {
completion({ throw ServiceErrorType.invalidResponse })
}
return
}
ServiceManager.log(response, withBody: data)
//here handling status code
}
}
And the error from server is below
{
"status" : 500,
"message" : "Required request part 'file' is not present",
"timestamp" : "2022-08-05T05:30:55.415+0000",
"path" : "/uploadFile",
"error" : "Internal Server Error"
}
Any suggestions?
As your code does not contain a reproduclible example, this is just a long shot.
The final boundary is definitely wrong. It has to end with two "-" ticks.
e.g.
body.append("\r\n--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
but there might be more going on here.
Good article on multipart form data
RFC
The boundary header can be an arbitary string. But it has to be unique in the request to seperate it from the datastream. Also in the body it has to start with two "-" and the last boundary line in the request has to end with two "-" ticks also.

How to send the image file with value as image, key as 'file'

As I am new to iOS, am stuck here for a while, I need to upload the image to a server with key and value as ("file": image), find the image as attached in postman.
I have tried almost every suggestion here How to upload images to a server in iOS with Swift?, Upload image to server - Swift 3
Here I have tried something but not getting output response because of the key not passed in the request
let url = URL(string: uploadurl);
let request = NSMutableURLRequest(url: url!);
request.httpMethod = "POST"
let boundary = "Boundary-\(NSUUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(image, 1)
if (imageData == nil) {
print("UIImageJPEGRepresentation return nil")
return
}
let body = NSMutableData()
//here I need to pass the data as ["file":image]
body.append(imageData!)
request.httpBody = body as Data
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if let data = data {
// do
let json = try!JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary
print("json value \(json)")
} else if let error = error {
print(error.localizedDescription)
}
})
task.resume()
Please suggest me, how to pass the these image in body as ["file": image].
Thanks in advance
You could use URLSession to upload a multipart/form-data
The upload
The function to upload the image
// build request URL
guard let requestURL = URL(string: "YOURURL") else {
return
}
// prepare request
var request = URLRequest(url: requestURL)
request.allHTTPHeaderFields = header
request.httpMethod = MethodHttp.post.rawValue
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
// built data from img
if let imageData = image.jpegData(compressionQuality: 1) {
request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "file", imageDataKey: imageData, boundary: boundary)
}
let task = URLSession.shared.dataTask(with: request,
completionHandler: { (data, _, error) -> Void in
if let data = data {
debugPrint("image uploaded successfully \(data)")
} else if let error = error {
debugPrint(error.localizedDescription)
}
})
task.resume()
The body
the function that will create the request body
func createBodyWithParameters(parameters: [String: String],
filePathKey: String,
imageDataKey: Data,
boundary: String) -> Data {
let body = NSMutableData()
let mimetype = "image/*"
body.append("--\(boundary)\r\n".data(using: .utf8) ?? Data())
body.append("Content-Disposition: form-data; name=\"\(filePathKey)\"; filename=\"\(filePathKey)\"\r\n".data(using: .utf8) ?? Data())
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: .utf8) ?? Data())
body.append(imageDataKey)
body.append("\r\n".data(using: .utf8) ?? Data())
body.append("--\(boundary)--\r\n".data(using: .utf8) ?? Data())
return body as Data
}
private func generateBoundaryString() -> String {
return "Boundary-\(Int.random(in: 1000 ... 9999))"
}
}
Data extension
extension NSMutableData {
func appendString(_ string: String) {
if let data = string.data(using: String.Encoding.utf8,
allowLossyConversion: true) {
append(data)
}
}
}
Try this. Save the file in documentDirectory. Add the file in body with boundary which is a random string. Then add the key of the file as name=\"file\"
if !fileName.isEmpty {
let pathComponents = [NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!, fileName]
outputFileURL = NSURL.fileURL(withPathComponents: pathComponents) //get the image file from documentDirectory
//add file to body (name=\"file\")
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"image.jpeg\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: image/*\r\n\r\n".data(using: String.Encoding.utf8)!)
do {
try body.append(Data(contentsOf: outputFileURL!))
} catch {
print(error)
}
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
}

How to do multipart/form-data post request with Swift?

let Url = String(format: "http://url/ios.php")
guard let serviceUrl = URL(string: Url) else { return }
let parameterDictionary :[String:String] = ["Episodes" : "http://url/anime/07-ghost.html"]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
request.httpBody = NSKeyedArchiver.archivedData(withRootObject: parameterDictionary)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}catch {
print(error)
}
}
}.resume()
}
I get error
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}
not sure if im sending data correctly, i think im setting httpbody incorectly
i even tried with json
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: []) else {
return
}
Swift 3,
Try this, Remove responseHandler parameter and any other if not use in your code
class func API_POST_FORM_DATA(param:[String : String], songData:Data?, fileName:String ,responseHandler : #escaping CompletionHandler)
{
let API_URL = API_POST_ADD_SONG_TO_PLAYLIST
print("API_URL : \(API_URL)")
let request = NSMutableURLRequest(url: URL(string: API_URL)!)
request.httpMethod = "POST"
let boundary = API_Calling.generateBoundaryString()
//define the multipart request type
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let body = NSMutableData()
let fname = fileName
let mimetype = "image/png"
//define the data post parameter
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"test\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("hi\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
if let songRawData = songData
{
body.append("Content-Disposition:form-data; name=\"song\"; filename=\"\(fname)\"\r\n".data(using: String.Encoding.utf8)!)
body.append(songRawData)
}
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
for (key, value) in param
{
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
}
request.httpBody = body as Data
// return body as Data
print("Fire....")
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
print("Complete")
if error != nil
{
print("error upload : \(error)")
responseHandler(nil)
return
}
do
{
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
responseHandler(json as NSDictionary?)
}else
{
print("Invalid Json")
}
}
catch
{
print("Some Error")
responseHandler(nil)
}
}
task.resume()
}
class func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}

Uploading an image and parameters with multipart/form-data in Swift

[WARNING]
As I am seeing that this question is getting noticed more than it should,
I want to tell you not to use any of the following code.
At the time I asked the question, Swift had less than a year, was moving fast, most of the libraries were not Swift-friendly and unstable.
I strongly recommend you to try using Alamofire or another library for that kind of task. But don't do it yourself.
[/WARNING]
I want to upload an image to a Drupal endpoint.
The problem I have is that I receive an HTTP 200 OK response with text/html content type. In the HTML response, there is a clear message that the node has been correctly created. But on the server side the image is not associated with the node.
Also I am not expecting text/html but application/json as I specify it in the Accept header.
It already works in the Android app using Android Rest Template. Here is the code for reference:
String url = getUrl("node/{info_id}/attach_file");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
if (user.isLoggedIn()) {
headers.add(user.getSessionName(), user.getSessionId());
headers.add("X-CSRF-Token", user.getToken());
headers.add("Cookie", user.getSessionName() + "=" + user.getSessionId());
}
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("files[field_mobileinfo_image]",
new FileSystemResource(info.getImageUri()));
parts.add("field_name", "field_mobileinfo_image");
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(parts, headers);
return getRestTemplate().exchange(url, HttpMethod.POST, request, Void.class, info.getId()).getBody();
I know I don't check the response in Android (Void.class) but everything works fine and the image is attached to the node on the server side.
Now on iOS in Swift I tried multiple things.
With AFNetworking:
func upload(mobileInfo: MobileInfo) {
let user = userService.load()
let url = Config.buildUrl("")
let manager = AFHTTPRequestOperationManager(baseURL: NSURL(string:url)!)
let serializer = AFHTTPRequestSerializer()
serializer.setValue(user.sessionId, forHTTPHeaderField: user.sessionName)
serializer.setValue(user.token, forHTTPHeaderField: "X-CSRF-Token")
serializer.setValue("\(user.sessionName)=\(user.sessionId)", forHTTPHeaderField: "Cookie")
manager.requestSerializer = serializer
manager.responseSerializer.acceptableContentTypes.removeAll(keepCapacity: false)
manager.responseSerializer.acceptableContentTypes.insert("application/json")
let imageData = UIImageJPEGRepresentation(mobileInfo.image, 0.3)
manager.POST("/node/\(mobileInfo.id)/attach_file", parameters: nil, constructingBodyWithBlock: { (formData) -> Void in
formData.appendPartWithFileData(
imageData,
name: "files[field_mobileinfo_image]",
fileName: "field_mobileinfo_image",
mimeType: "image/jpeg")
formData.appendPartWithFormData("field_mobileinfo_image".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true), name: "field_name")
},
success: { (operation, data) -> Void in
println(data)
}) { (operation, error) -> Void in
println(error)
}
}
Manually with information grabbed from other stackoverflow questions:
func upload2(mobileInfo: MobileInfo) {
let user = userService.load()
let imageData = UIImageJPEGRepresentation(mobileInfo.image, 0.3)
let url = NSURL(string:Config.buildUrl("/node/\(mobileInfo.id)/attach_file"))!
println(url)
var request = NSMutableURLRequest(URL: url)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var boundary = "---------------------------14737809831466499882746641449"
var contentType = "multipart/form-data; boundary=\(boundary)"
println(contentType)
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("\(user.sessionName)=\(user.sessionId)", forHTTPHeaderField: "Cookie")
request.addValue(user.sessionId, forHTTPHeaderField: user.sessionName)
request.addValue(user.token, forHTTPHeaderField: "X-CSRF-Token")
println(request.allHTTPHeaderFields)
var body = NSMutableData()
body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"field_name\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("field_mobileinfo_image".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"files[field_mobileinfo_image]\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: application/octet-stream\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(imageData)
body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
var returnData = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
var returnString = NSString(data: returnData!, encoding: NSUTF8StringEncoding)
println("returnString \(returnString)")
}
With SRWebClient:
func upload3(mobileInfo: MobileInfo) {
let user = userService.load()
let imageData:NSData = NSData(data: UIImageJPEGRepresentation(mobileInfo.image, 0.3))
SRWebClient.POST("http://master.test.lesfrontaliers.lu/node/\(mobileInfo.id)/attach_file")
.headers(["Accept": "application/json",
user.sessionName: user.sessionId,
"X-CSRF-Token": user.token,
"Cookie": "\(user.sessionName)=\(user.sessionId)"])
.data(imageData, fieldName:"files[field_mobileinfo_image]", data:["field_name":"field_mobileinfo_image"])
.send({ (response: AnyObject!, status: Int) -> Void in
println(status)
println(response)
},failure:{(error:NSError!) -> Void in
println(error)
})
}
Please save me! ;-)
I tried so many things to make it work that I can't see anymore if I am doing something wrong. It seems ok for me. The only difference I can see is that I am not storing the image on the filesystem but directly sending the binary data which is the same thing in the end.
Here is an image of the request created in Postman (working and receiving json)
[EDIT] If it can help someone here is the correct code of the wrong part of the above manual request:
var body = NSMutableData()
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"field_name\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("field_mobileinfo_image\r\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"files[field_mobileinfo_image]\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(imageData)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody = body
Don't know if this will work for what you are trying to do but we use this to upload images, the key difference is to use filename and Content-type:
[self appendBody:body data:[NSString stringWithFormat:#"Content-Disposition: form-data; name=\"%#\"; filename=\".jpg\"\r\n", key]];
[self appendBody:body data:#"Content-Type: image/jpeg\r\n\r\n"];
[body appendData:imageData];
For any swift 2.0 JSON Request AND PHP code :- ( Manual )
let imageData = UIImageJPEGRepresentation(userImage, 0.3)
let url:NSURL = NSURL(string: serverURL!)! // Give ur request URL
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
let boundary = "---------------------------14737809831466499882746641449"
let contentType = "multipart/form-data; boundary=\(boundary)"
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
let body = NSMutableData()
body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Disposition: form-data; name=\"userfile\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Type: image/jpeg\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Content-Transfer-Encoding: binary\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(imageData!)
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody = body
PHP Code :-
<?php
//http://192.168.1.154/Contact/uploadImgwebservice.php
//print the username and password using php
echo $_POST[‘username’];
echo $_POST[‘password’];
//upload your file
$uploaddir = ‘./uploads/’;
$file = basename($_FILES[‘userfile’][‘name’]);
$uploadfile = $uploaddir . $file;
if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) {
echo “http://192.168.1.154/Contact/uploads/{$file}”;
}
?>

Resources