NIKHIL MAURYA NIKHIL MAURYA - 11 months ago 90
iOS Question

Swift3 video file upload along with one more form parameter(can be skipped from form and sent as url path)

I have searched for a long time but didn't find any good resource on how to do this.
The api expects one form parameter "user_id"(for now sending its as urlpath not form parameter) and other "file" for the video file. please provide some code sample either using URLSession Task or any library for iOS.

Tried Alamofire:

Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(self.fileurl, withName: "file")
}, to:"http://www.www.www/upload/8590",
headers: ["Authorization": "Bearer \(SharedPreferences.preferences.getKeyValue(key: Constants.AUTH_TOKEN_key))"] )
{ (result) in
switch result {
case .success(let upload, _ , _):

upload.uploadProgress(closure: { (progress) in

print("uploding>>>>>>")
})

upload.responseJSON { response in
print(response)
print("done")

}

case .failure(let encodingError):
print("failed")
print(encodingError)

}


This throws 500 from server saying it can't read Header first byte using UTF-8 encoding.

message = "An Error OccuredInvalid header string: 'utf8' codec can't decode byte 0x9b in position 1: invalid start byte";
result = "Traceback (most recent call last):\n File \"/var/www/wb_ios/wb_app/views.py\", line 94, in post\n user_auth = jwt_decode_handler(auth).get('sub')\n File \"/usr/local/lib/python2.7/dist-packages/rest_framework_jwt/utils.py\", line 104, in jwt_decode_handler\n unverified_payload = jwt.decode(token, None, False)\n File \"/usr/local/lib/python2.7/dist-packages/jwt/api_jwt.py\", line 70, in decode\n payload, signing_input, header, signature = self._load(jwt)\n File \"/usr/local/lib/python2.7/dist-packages/jwt/api_jws.py\", line 177, in _load\n raise DecodeError('Invalid header string: %s' % e)\nDecodeError: Invalid header string: 'utf8' codec can't decode byte 0x9b in position 1: invalid start byte\n";
status = 500;


}

Additionally, I can use postman to send the video successfully. Using form-data field like shown in images.
body
Headers

finally I also tried :

let url = NSURL(string: "http://www.www.www/upload/8590")
let request = NSMutableURLRequest(url: url! as URL)
let boundary = "------------------------your_boundary"

request.httpMethod = "POST"
request.setValue("ios", forHTTPHeaderField: "client")
request.setValue(Constants.AUTH_KEY, forHTTPHeaderField: Constants.AUTH_KEY_key)
request.setValue("Bearer " + SharedPreferences.preferences.getKeyValue(key: Constants.AUTH_TOKEN_key)!, forHTTPHeaderField: Constants.AUTH_AUTHORIZATION_key)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var movieData: NSData?
do {
movieData = try NSData(contentsOfFile: fileurl.path, options: NSData.ReadingOptions.alwaysMapped)
print(movieData)
} catch _ {
movieData = nil
return
}

let body = NSMutableData()

// change file name whatever you want
let filename = "upload.mov"
let mimetype = "video/mov"

body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(filename)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(movieData! as Data)
request.httpBody = body as Data

let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in

guard let _:NSData = data as! NSData, let _:URLResponse = response, error == nil else {
print("error")
return
}

let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(dataString)
}

task.resume()


this also throws error like this:

{"status":500,"message":"An Error Occuredu'file'","result":"Traceback (most recent call last):\n File \"/var/www/wb_ios/wb_app/views.py\", line 104, in post\n file_obj = request.data['file']\n File \"/usr/local/lib/python2.7/dist-packages/django/utils/datastructures.py\", line 85, in __getitem__\n raise MultiValueDictKeyError(repr(key))\nMultiValueDictKeyError: \"u'file'\"\n"})

Answer Source

Swift3.0

Alamofire.upload(multipartFormData: { MultipartFormData in
            for (key, value) in parameter {
                MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
            }

// here you can upload only mp4 video
                multipartFormData.append(self.fileurl!, withName: "file", fileName: "video.mp4", mimeType: "video/mp4")
// here you can upload any type of video            
                 multipartFormData.append((self.fileurl.data(using: String.Encoding.utf8, allowLossyConversion: false))!, withName: "File")

            print(MultipartFormData)
        },to:"http://www.www.www/upload/8590",headers: ["Authorization": "Bearer \(SharedPreferences.preferences.getKeyValue(key: Constants.AUTH_TOKEN_key))"]
            )
        { (result) in

            switch result {
            case .success(let upload, _, _):
                upload.uploadProgress(closure: { (progress) in
                    print("Upload Progress: \(progress.fractionCompleted)")
                })
                upload.responseJSON { response in
                    print(response.result.value ?? String())
                    print(response.data ?? NSData())
                    // send to completion block
                    completion(response.data as AnyObject? ?? NSData())
                }

            case .failure(let encodingError):
                print(encodingError)
                errorOccured(encodingError as NSError?)

            }
        }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download