Upload image with multipart form-data only in Swift 4.2
Please check my solution which is taken parameters and images.I have tested with PHP, .net, java.
class func request(withImages path:APIMethods, method:URLMethod, token : String?, headers:[String:String]?, parameters: [String:Any]?,imageNames : [String], images:[Data], completion: @escaping(Any?, Error?, Bool)->Void) {
if !Reachability.isConnectedToNetwork() {
DispatchQueue.main.async {
showAlert(message: AppMessages.connectionFailed.rawValue)
}
dissmissHud()
return
}
var stringUrl = "\(APIManager.url)\(APIMethods.preFix.rawValue)\(path.rawValue)"
if method == .get, let lastPath = parameters?.values.first as? String {
stringUrl += lastPath
}else{
stringUrl += token ?? ""
}
// generate boundary string using a unique per-app string
let boundary = UUID().uuidString
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
print("\n\ncomplete Url :-------------- ",stringUrl," \n\n-------------: complete Url")
guard let url = URL(string: stringUrl) else { return }
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
if headers != nil{
print("\n\nHeaders :-------------- ",headers as Any,"\n\n --------------: Headers")
for (key, value) in headers! {
request.setValue(value, forHTTPHeaderField: key)
}
}
// Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
// And the boundary is also set here
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
if parameters != nil{
for(key, value) in parameters!{
// Add the reqtype field and its value to the raw http request data
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
data.append("\(value)".data(using: .utf8)!)
}
}
for (index,imageData) in images.enumerated() {
// 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=\"\(imageNames[index])\"; filename=\"\(imageNames[index])\"\r\n".data(using: .utf8)!)
data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
data.append(imageData)
}
// End the raw http request data, note that there is 2 extra dash ("-") at the end, this is to indicate the end of the data
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
// Send a POST request to the URL, with the data we created earlier
session.uploadTask(with: request, from: data, completionHandler: { data, response, error in
if let checkResponse = response as? HTTPURLResponse{
if checkResponse.statusCode == 200{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.allowFragments]) else {
completion(nil, error, false)
return
}
let jsonString = String(data: data, encoding: .utf8)!
print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
print(json)
completion(json, nil, true)
}else{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
completion(nil, error, false)
return
}
let jsonString = String(data: data, encoding: .utf8)!
print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
print(json)
completion(json, nil, false)
}
}else{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
completion(nil, error, false)
return
}
completion(json, nil, false)
}
}).resume()
}
extension Data {
/// Append string to Data
///
/// Rather than littering my code with calls to `data(using: .utf8)` to convert `String` values to `Data`, this wraps it in a nice convenient little extension to Data. This defaults to converting using UTF-8.
///
/// - parameter string: The string to be added to the `Data`.
mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
if let data = string.data(using: encoding) {
append(data)
}
}
}
Related videos on Youtube
Nidhi Tiwari
I help clients mobile applications. Results-oriented iOS developer with more than 7 years’ experience writing highly readable, clean, maintainable source code. Developed applications for iPhone and iPad that offer users an intuitive, friendly interface, and successfully executed on itunes.I have worked in multiple areas in mid size companies related to online products/services ranging from application development to user interface design, and project management. Results include robust downloads, activation, session lengths, retention rates, revenue increases and referrals.I am involved in product design and development for both MVPs and full featured apps. When needed I also help refine business models, explore revenue/monetization options, construct distribution strategies, and build customer acquisition plans. Technical Skills Summary :- • Good knowledge of Objective C & Swift programming language. • Very proficient in Web service integrations: SOAP, JSON, XML. • Good understanding of iOS Design Patterns. • Good knowledge of CoreData. • Experience in UI development. • Building interfaces via storyboard files, nibs, or programmatically. • Integrating third-party frameworks and libraries. • Memory management Process, ARC. • Familiar with iPad device orientations techniques and Localization. • Familiar with Apple’s provisioning profile and certificates. • Familiar with app store submission process. • Good problem solving skills and resourcefulness to find solutions through self-study and research. • Good experience working under pressure - individually and also as a team member.
Updated on May 23, 2022Comments
-
Nidhi Tiwari about 2 years
I tried lots of solution. I get some but they were using
objective c code
in somewhere. I need solution only inswift 4.2
and without any third party (likeAlamofire
).It is working fine usingobjective c
classes .I have been able to make POST request with only, headers and other parameters and image as:
Upload files using multipart request - Swift 4
How to do multipart/form-data post request with Swift?
Multipart-form (image,parameters,headers) Post request with Alamofire in swift
Upload image with multipart form-data iOS in Swift
How to upload images to a server in iOS with Swift?
func sendFile( urlPath:String, fileName:String, data:NSData, completionHandler: (NSURLResponse!, NSData!, NSError!) -> Void){ var url: NSURL = NSURL(string: urlPath)! var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url) request1.HTTPMethod = "POST" let boundary = generateBoundary() let fullData = photoDataToFormData(data,boundary:boundary,fileName:fileName) request1.setValue("multipart/form-data; boundary=" + boundary, forHTTPHeaderField: "Content-Type") // REQUIRED! request1.setValue(String(fullData.length), forHTTPHeaderField: "Content-Length") request1.HTTPBody = fullData request1.HTTPShouldHandleCookies = false let queue:NSOperationQueue = NSOperationQueue() NSURLConnection.sendAsynchronousRequest( request1, queue: queue, completionHandler:completionHandler) } // this is a very verbose version of that function // you can shorten it, but i left it as-is for clarity // and as an example func photoDataToFormData(data:NSData,boundary:String,fileName:String) -> NSData { var fullData = NSMutableData() // 1 - Boundary should start with -- let lineOne = "--" + boundary + "\r\n" fullData.appendData(lineOne.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!) // 2 let lineTwo = "Content-Disposition: form-data; name=\"image\"; filename=\"" + fileName + "\"\r\n" NSLog(lineTwo) fullData.appendData(lineTwo.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!) // 3 let lineThree = "Content-Type: image/jpg\r\n\r\n" fullData.appendData(lineThree.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!) // 4 fullData.appendData(data) // 5 let lineFive = "\r\n" fullData.appendData(lineFive.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!) // 6 - The end. Notice -- at the start and at the end let lineSix = "--" + boundary + "--\r\n" fullData.appendData(lineSix.dataUsingEncoding( NSUTF8StringEncoding, allowLossyConversion: false)!) return fullData }
-
Thet Htun over 3 yearsThanks! Hope this help to anyone who might encounter similar silly mistakes 😄Forgot to close the request & had a few head scratch :) missed this part => data.append("\r\n--(boundary)--\r\n".data(using: .utf8)!).
-
Caterina Dmitrieva over 2 yearsThank you! worked with Django REST backend as well
-
Vinod Kumar over 2 yearsWelcome @CaterinaDmitrieva