Uploading text file using Alamofire - ios

I have a text file saved in a directory inside the document directory
I want to upload this file to stream (upload) to the server using Alamofire but I'm getting an error and I don't follow what is the error mean
the response should be a string, the problem isn't in the format of the response data even if I used responseString I'm getting an error.
This my code:
let folder = getFolder()
let textFile = fileUrl?.appendingPathComponent(fileTemp)
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
let finalUrl = url + "/myMethod"
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(textFile!, withName: "file")
},
to: finalUrl,headers:headers,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}})
And this is the response value I am getting:
Status Code: 400, Headers {
"Cache-Control" = (
private
);
"Content-Length" = (
1647
);
"Content-Type" = (
"text/html"
);
Date = (
"Thu, 06 Sep 2018 09:32:47 GMT"
);
Server = (
"Microsoft-IIS/8.5"
);
"X-AspNet-Version" = (
"4.0.30319"
);
"X-Powered-By" = (
"ASP.NET"
); } } [Data]: 1647 bytes [Result]: FAILURE: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error
Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character
3." UserInfo={NSDebugDescription=Invalid value around character 3.}))
Does anyone have any idea about what I'm doing wrong?
Thanks in advance!

you need to specify the upload format is text
Change this:
multipartFormData.append(textFile!, withName: "file")
To this:
multipartFormData.append(textFile!, withName: "file", fileName: filename, mimeType: "text/plain")

Related

Alamofire changes multipart/form-data encoding depending on input

Working on an iOS project I found out that Alamofire changes the Content-Transfer-Encoding of a multipart/form-data field depending on the field value.
Goal
Update an image with some informations (unicode strings) to an endpoint.
Details
I define the form's fields values as follows:
let formFields: [String: String] = [
"key": _model
]
I upload the entire form (image + informations) as follows:
Alamofire.upload(
multipartFormData: { multipartFormData in
// 1. The form's fields
for (key, value) in formFields {
guard let byteString = value.data(using: String.Encoding.utf8, allowLossyConversion: false) else { continue }
multipartFormData.append(byteString, withName: key)
}
// 2. The picture
let fileName = "file.jpeg"
multipartFormData.append(pictureData, withName: ParameterKeys.BikeImage, fileName: fileName, mimeType: "image/jpeg")
},
to: _url,
method: .post,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _): /* Called when the encoding succeds. */
upload.validate(statusCode: 200..<300)
upload.uploadProgress { progress in // main queue by default
progressHandler(progress)
}
upload.response { (response) in
responseHandler(response)
}
case .failure(let error): /* Called when the encoding fails. */
failureHandler(error)
}
}
)
Behaviour 0
_model is "Standard" ✅
multipartFormData.append(byteString, ...) appends "5374616e64617264" in the form ✅
The server gets "Standard" without Content-Transfer-Encoding ⁉️
Behaviour 1
_model is "Ström Bike" ✅
multipartFormData.append(byteString, ...) appends "537472c3b66d2042696b65" in the form ✅
The server gets "Str=C3=B6m Bike" with Content-Transfer-Encoding: quoted-printable ⁉️
Behaviour 2
_model is "Abräcadabra" ✅
multipartFormData.append(byteString, ...) appends "416272c3a463616461627261" in the form ✅
The server gets "QWJyw6RjYWRhYnJh" with Content-Transfer-Encoding: base64 ⁉️
Conclusion
On the server, I cannot determine the format of the form data. Is there a way to specify the type of encoding to use for the form fields?
Thank you in advance.

convert alamofire json response to variable

I have a question that I already asked several times on stackoverflow and I have tried all of them, there is none of them worked. So I would love to summarize the question for another time, and try to describe it more precise.
I am building an app sending a picture to a python back end for the result of image recognition in xcode swift.
And I am using Alamofire to upload,
here is the uploading part:
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imageData!, withName: "pic", fileName: "filename.png", mimeType: "image/png")
}, to: "http:123456.com/image",
method: .post,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseString { response in
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}
And here is the json response I got from the server end:
[Response]: <NSHTTPURLResponse: 0x600000237de0> { URL: 1234/image } { Status Code: 200, Headers {
"Content-Length" = (
348
);
"Content-Type" = (
"text/html; charset=utf-8"
);
Date = (
"Mon, 09 Apr 2018 20:59:30 GMT"
);
Server = (
"Werkzeug/0.12.2 Python/2.7.12"
);
} }
[Data]: 348 bytes
[Result]: SUCCESS: {
"prediction": [
{
"name": "marshmallow",
"value": 0.2800232470035553
},
{
"name": "caesar salad",
"value": 0.090629942715168
},
{
"name": "egg",
"value": 0.07480788230895996
},
{
"name": "apple",
"value": 0.049235329031944275
},
{
"name": "chickpea",
"value": 0.04692944884300232
}
]
}
[Timeline]: Timeline: { "Request Start Time": 545000363.584, "Initial Response Time": 545000363.642, "Request Completed Time": 545000370.462, "Serialization Completed Time": 545000370.487, "Latency": 0.058 secs, "Request Duration": 6.879 secs, "Serialization Duration": 0.025 secs, "Total Duration": 6.903 secs }
So, the purpose I want to have, is just print the name of the first prediction's name.
like the output is
outcome is marshmallow with a value of 0.28
I have tried several ways:
First, I want to have a struct to store the name as string, value as double, and use a loop to parse it. But whatever I tried, I always get a "null" as output, or nothing.
Any suggestions on this? Thanks in advance.
try this:
upload.responseJSON { response in
if let result = response.result.value {
let json = result as! [String: Any]
if let predictionArray = json["prediction"] as? [[String: Any]],
let firstPrediction = predictionArray.first {
print(firstPrediction)
}
print(json)
}
}

Unable to get response from Google distance matrix api

I am using google distance matrix API and i am using following code
let headers: HTTPHeaders = [ "Accept": "application/json", "Content-Type": "application/json" ]
let url = "https://maps.googleapis.com/maps/api/distancematrix/json?&origins=\(start)&destinations=\(end)&key=AIzaSyDvt_KiUCtdb1kPEw4E4Dt68EuiF8PosAg"
let header: HTTPHeaders = [ "Accept": "application/json", "Content-Type": "application/json" ]
Alamofire.request( url, method: .get, encoding: JSONEncoding.default, headers : header) .responseString { response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result)
}
as per this Unable to fetch Response For Google Distance matrix in Swift i am passing header but still i am getting following error.
Here is my URL with start and end
"https://maps.googleapis.com/maps/api/distancematrix/json?&origins=Nanpura, Surat, Gujarat 395008, India&destinations=Adajan, Surat, Gujarat, India&key=AIzaSyDvt_KiUCtdb1kPEw4E4Dt68EuiF8PosAg "
You should encode url, try with this
let url = "https://maps.googleapis.com/maps/api/distancematrix/json?&origins=Nanpura, Surat, Gujarat 395008, India&destinations=Adajan, Surat, Gujarat, India&key=AIzaSyDvt_KiUCtdb1kPEw4E4Dt68EuiF8PosAg"
let encodedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let header: HTTPHeaders = [ "Accept": "application/json", "Content-Type": "application/json" ]
Alamofire.request(encodedUrl! , method: .get,encoding: JSONEncoding.default, headers: header)
.responseJSON { (data) in
print(data)
}
this will also work,
Alamofire.request(encodedUrl!, method: .get,encoding: JSONEncoding.default, headers: header)
.responseString {response in
print(response.request) // original URL request
print(response.response) // HTTP URL response
print(response.data) // server data
print(response.result)
}
Response will be like this,
SUCCESS: {
"destination_addresses" = (
"Adajan, Surat, Gujarat, India"
);
"origin_addresses" = (
"Nanpura, Surat, Gujarat 395008, India"
);
rows = (
{
elements = (
{
distance = {
text = "2.4 km";
value = 2433;
};
duration = {
text = "6 mins";
value = 373;
};
status = OK;
}
);
}
);
status = OK;
}
I checked the request and it is working fine. I guess you are missing privacy setting in info.plist

iOS Swift uploading PDF file with Alamofire (Multipart)

I'm currently developing an application using iOS 10 and Swift 3 and Alamofire 4
The purpose of this application is to upload a PDF file generated previously.
The PDF generation is working perfectly and the file is created.
However the upload doesn’t work…
I received a success response but the file is not uploaded.
My server response
Multi part Content-Type => multipart/form-data; boundary=alamofire.boundary.56958be35bdb49cb
Multi part Content-Length => 293107
Multi part Content-Boundary => alamofire.boundary.56958be35bdb49cb
responses
SUCCESS: {
uploadedFiles = (
{
details = " Key=Content-Disposition - values=[form-data; name=\"pdfDocuments\"] length=8";
storedFileName = "/var/www/pdf/17/009/22/TMP104150531290406.tmp";
type = PDF;
uploadedDate = 1483999296701;
uploadedFileName = UnknownFile;
}
);
}
end responses
I’m using multi-part to upload my file as Data as you can see here
File url is fine.
I have searched on SO but didn’t find any solution working…
Here you can see my Controller
Alamofire.upload(
multipartFormData: {
multipartFormData in
if let urlString = urlBase2 {
let pdfData = try! Data(contentsOf: urlString.asURL())
var data : Data = pdfData
multipartFormData.append(data as Data, withName:"test.pdf", mimeType:"application/pdf")
for (key, value) in body {
multipartFormData.append(((value as? String)?.data(using: .utf8))!, withName: key)
}
print("Multi part Content -Type")
print(multipartFormData.contentType)
print("Multi part FIN ")
print("Multi part Content-Length")
print(multipartFormData.contentLength)
print("Multi part Content-Boundary")
print(multipartFormData.boundary)
}
},
to: url,
method: .post,
headers: header,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
print(" responses ")
print(response)
print("end responses")
onCompletion(true, "Something bad happen...", 200)
}
case .failure(let encodingError):
print(encodingError)
onCompletion(false, "Something bad happen...", 200)
}
})
Thanks in advance for the help.
Regards
I have just found my solution to fix this bug.
I have forgot a parameter for the file name.
multipartFormData.append(pdfData, withName: "pdfDocuments", fileName: namePDF, mimeType:"application/pdf")
Thanks for the help.

Alamofire invalid value around character 0

Alamofire.request(.GET, "url").authenticate(user: "", password: "").responseJSON() {
(request, response, json, error) in
println(error)
println(json)
}
This is my request with Alamofire, for a certain request it sometime works, but sometimes i get:
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x78e74b80 {NSDebugDescription=Invalid value around character 0.})
I've read that this can be due to invalid JSON, but the response is a static json string that i have validated in JSON validator as valid. It does contain å ä ö characters and some HTML.
Why am i getting this error sometimes?
I also faced same issue. I tried responseString instead of responseJSON and it worked. I guess this is a bug in Alamofire with using it with django.
In my case , my server URL was incorrect. Check your server URL !!
I got same error while uploading image in multipart form in Alamofire as i was using
multipartFormData.appendBodyPart(data: image1Data, name: "file")
i fixed by replacing by
multipartFormData.appendBodyPart(data: image1Data, name: "file", fileName: "myImage.png", mimeType: "image/png")
Hope this help someone.
May this Help YOu
Alamofire.request(.GET, "YOUR_URL")
.validate()
.responseString { response in
print("Success: \(response.result.isSuccess)")
print("Response String: \(response.result.value)")
}
The same issue happened to me and it actually ended up being a server issue since the content type wasn't set.
Adding
.validate(contentType: ["application/json"])
To the request chain solved it for me
Alamofire.request(.GET, "url")
.validate(contentType: ["application/json"])
.authenticate(user: "", password: "")
.responseJSON() { response in
switch response.result {
case .Success:
print("It worked!")
print(response.result.value)
case .Failure(let error):
print(error)
}
}
I got the same error. But i found the solution for it.
NOTE 1: "It is not Alarmofire error", it's bcouse of server error.
NOTE 2: You don't need to change "responseJSON" to "responseString".
public func fetchDataFromServerUsingXWWWFormUrlencoded(parameter:NSDictionary, completionHandler: #escaping (_ result:NSDictionary) -> Void) -> Void {
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
let completeURL = "http://the_complete_url_here"
Alamofire.request(completeURL, method: .post, parameters: (parameter as! Parameters), encoding: URLEncoding.default, headers: headers).responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)") // your JSONResponse result
completionHandler(JSON as! NSDictionary)
}
else {
print(response.result.error!)
}
}
}
This is how I managed to resolve the Invalid 3840 Err.
The error log
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}))
It was with Encoding Type used in the Request, The Encoding Type used should be acceptedin your Server-Side.
In-order to know the Encoding I had to run through all the Encoding Types:
default/
methodDependent/
queryString/
httpBody
let headers: HTTPHeaders = [
"Authorization": "Info XXX",
"Accept": "application/json",
"Content-Type" :"application/json"
]
let parameters:Parameters = [
"items": [
"item1" : value,
"item2": value,
"item3" : value
]
]
Alamofire.request("URL",method: .post, parameters: parameters,encoding:URLEncoding.queryString, headers: headers).responseJSON { response in
debugPrint(response)
}
It also depends upon the response we are recieving use the appropriate
responseString
responseJSON
responseData
If the response is not a JSON & just string in response use responseString
Example: in-case of login/ create token API :
"20dsoqs0287349y4ka85u6f24gmr6pah"
responseString
I solved using this as header:
let header = ["Content-Type": "application/json",
"accept": "application/json"]
In my case, there was an extra / in the URL .
Maybe it is too late but I solved this problem in another way not mentioned here:
When you use .responseJSON(), you must set the response header with content-type = application/json, if not, it'll crash even if your body is a valid JSON. So, maybe your response header are empty or using another content-type.
Make sure your response header is set with content-type = application/json to .responseJSON() in Alamofire work properly.
Hey guys this is what I found to be my issue: I was calling Alamofire via a function to Authenticate Users: I used the function "Login User" With the parameters that would be called from the "body"(email: String, password: String) That would be passed
my errr was exactly:
optional(alamofire.aferror.responseserializationfailed(alamofire.aferror.responseserializationfailurereason.jsonserializationfailed(error domain=nscocoaerrordomain code=3840 "invalid value around character 0." userinfo={nsdebugdescription=invalid value around character 0
character 0 is the key here: meaning the the call for the "email" was not matching the parameters: See the code below
func loginUser(email: String, password: String, completed: #escaping downloadComplete) {
let lowerCasedEmail = email.lowercased()
let header = [
"Content-Type" : "application/json; charset=utf-8"
]
let body: [String: Any] = [
"email": lowerCasedEmail,
"password": password
]
Alamofire.request(LOGIN_USER, method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in
if response.result.error == nil {
if let data = response.result.value as? Dictionary<String, AnyObject> {
if let email = data["user"] as? String {
self.userEmail = email
print(self.userEmail)
}
if let token = data["token"] as? String {
self.token_Key = token
print(self.token_Key)
}
"email" in function parameters must match the let "email" when parsing then it will work..I no longer got the error...And character 0 was the "email" in the "body" parameter for the Alamofire request:
Hope this helps
I was sending the improper type (String) to the server in my parameters (needed to be an Int).
Error was resolved after adding encoding: JSONEncoding.default with Alamofire.
Alamofire.request(urlString, method: .post, parameters:
parameters,encoding:
JSONEncoding.default, headers: nil).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
The application I was working on this morning had the same error. I believed it to be a server side error since I was unable to upload a user image.
However, upon checking my custom API, I realized that after adding an SSL certificate to my website that I had not updated the api.swift URLs, the data was unable to post:
let HOME_URL = "http://sitename.io"
let BASE_URL = "http://sitename.io/api"
let UPLOAD_URL = "http://sitename.io/api/user/upload"
I changed the URL's to https://. Problem solved.
In my case I have to add this Key: "Accept":"application/json" to my header request.
Something like this:
let Auth_header: [String:String] = ["Accept":"application/json", "Content-Type" : "application/json", "Authorization":"Bearer MyToken"]
I hope that this can help someone.
I face same issue and problem is in params.
let params = [kService: service,
kUserPath: companyModal.directory_path,
kCompanyDomain: UserDefaults.companyDomain,
kImageObject: imageString,
kEntryArray: jsonString,
kUserToken: UserDefaults.authToken] as [String : Any]
companyModal.directory_path is url. it coerced from string to any which create issues at server side. To resolve this issue I have to give default value which make it string value.
let params = [kService: kGetSingleEntry,
kUserPath: companyModal.directory_path ?? "",
kCompanyDomain: UserDefaults.companyDomain,
kUserToken: UserDefaults.authToken,
kEntryId: id,
] as [String: Any]
Probably you have "/" at the end of your path. If it is not GET request, you shouldn't put "/" at the end, otherwise you'll get the error
I Changed mimeType from "mov" to "multipart/form-data".
Alamofire.upload(multipartFormData: { (multipartFormData) in
do {
let data = try Data(contentsOf: videoUrl, options: .mappedIfSafe)
let fileName = String(format: "ios-video_%#.mov ", profileID)
multipartFormData.append(data, withName: "video", fileName: fileName, mimeType: "multipart/form-data")
} catch {
completion("Error")
}
}, usingThreshold: .init(), to: url,
method: .put,
headers: header)
Worked for me.. :)
For my case:
let header = ["Authorization": "Bearer \(Authserices.instance.tokenid)"]
I forgot the space before \ (after Bearer)
In my case error was due to duplicate email. You can recheck your API on postman to see if response there is OK or not.
In my case, I tried using Postman to get API and this error come from backend.

Resources