Skip to content

Instantly share code, notes, and snippets.

@ncerezo
Last active November 30, 2022 03:17
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save ncerezo/b1991f8dfac01cb162c0 to your computer and use it in GitHub Desktop.
Save ncerezo/b1991f8dfac01cb162c0 to your computer and use it in GitHub Desktop.
Alamofire multipart upload
//
// FileUploader.swift
//
// Copyright (c) 2015 Narciso Cerezo Jiménez. All rights reserved.
// Largely based on this stackoverflow question: http://stackoverflow.com/questions/26121827/uploading-file-with-parameters-using-alamofire/28467829//
import Foundation
import Alamofire
private struct FileUploadInfo {
var name:String
var mimeType:String
var fileName:String
var url:NSURL?
var data:NSData?
init( name: String, withFileURL url: NSURL, withMimeType mimeType: String? = nil ) {
self.name = name
self.url = url
self.fileName = name
self.mimeType = "application/octet-stream"
if mimeType != nil {
self.mimeType = mimeType!
}
if let _name = url.lastPathComponent {
fileName = _name
}
if mimeType == nil, let _extension = url.pathExtension {
switch _extension.lowercaseString {
case "jpeg", "jpg":
self.mimeType = "image/jpeg"
case "png":
self.mimeType = "image/png"
default:
self.mimeType = "application/octet-stream"
}
}
}
init( name: String, withData data: NSData, withMimeType mimeType: String ) {
self.name = name
self.data = data
self.fileName = name
self.mimeType = mimeType
}
}
class FileUploader {
private var parameters = [String:String]()
private var files = [FileUploadInfo]()
private var headers = [String:String]()
func setValue( value: String, forParameter parameter: String ) {
parameters[parameter] = value
}
func setValue( value: String, forHeader header: String ) {
headers[header] = value
}
func addParametersFrom( #map: [String:String] ) {
for (key,value) in map {
parameters[key] = value
}
}
func addHeadersFrom( #map: [String:String] ) {
for (key,value) in map {
headers[key] = value
}
}
func addFileURL( url: NSURL, withName name: String, withMimeType mimeType:String? = nil ) {
files.append( FileUploadInfo( name: name, withFileURL: url, withMimeType: mimeType ) )
}
func addFileData( data: NSData, withName name: String, withMimeType mimeType:String = "application/octet-stream" ) {
files.append( FileUploadInfo( name: name, withData: data, withMimeType: mimeType ) )
}
func uploadFile( request sourceRequest: NSURLRequest ) -> Request? {
var request = sourceRequest.mutableCopy() as! NSMutableURLRequest
let boundary = "FileUploader-boundary-\(arc4random())-\(arc4random())"
request.setValue( "multipart/form-data;boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let data = NSMutableData()
for (name, value) in headers {
request.setValue(value, forHTTPHeaderField: name)
}
// Amazon S3 (probably others) wont take parameters after files, so we put them first
for (key, value) in parameters {
data.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
for fileUploadInfo in files {
data.appendData( "\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)! )
data.appendData( "Content-Disposition: form-data; name=\"\(fileUploadInfo.name)\"; filename=\"\(fileUploadInfo.fileName)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
data.appendData( "Content-Type: \(fileUploadInfo.mimeType)\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
if fileUploadInfo.data != nil {
data.appendData( fileUploadInfo.data! )
}
else if fileUploadInfo.url != nil, let fileData = NSData(contentsOfURL: fileUploadInfo.url!) {
data.appendData( fileData )
}
else { // ToDo: report error
return nil
}
}
data.appendData("\r\n--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return Alamofire.upload( request, data )
}
}
// This example uploads a file called example.png found in the app resources
let fileURL = NSBundle.mainBundle().URLForResource("example", withExtension: "png")
let fileUploader = FileUploader()
// we can add multiple files
// this would be equivalent to: <input type="file" name="myFile"/>
fileUploader.addFileURL(fileURL!, withName: "myFile")
// we can add NSData objects directly
let data = UIImage(named: "sample")
fileUploader.addFileData( UIImageJPEGRepresentation(data,0.8), withName: "mySecondFile", withMimeType: "image/jpeg" )
// we can also add multiple aditional parameters
// this would be equivalent to: <input type="hidden" name="folderName" value="sample"/>
fileUploader.setValue( "sample", forParameter: "folderName" )
// put your server URL here
var request = NSMutableURLRequest( URL: NSURL(string: "http://myserver.com/uploadFile" )! )
request.HTTPMethod = "POST"
fileUploader.uploadFile(request: request)
@vinod1988
Copy link

How to get the response from server?

@tiego62
Copy link

tiego62 commented Jan 15, 2016

Thanks for your job !
I can not upload files to 2 MB superiors when my server is parametrer to 6MB. Did you have a solution?

@thanhhaiqtvn
Copy link

can you sent me php file web service ?

@Vivekban
Copy link

handle response by following code ->

               req = fileUploader.uploadFile(request: request)
                    .progress { [weak self] bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
                           //  To update your ui, dispatch to the main queue.
                           dispatch_async(dispatch_get_main_queue()) {
                           print("Total bytes written on main queue: \(totalBytesWritten)....\(totalBytesExpectedToWrite)")
                         }
                     }
                    .responseJSON { [weak self] response in
                     debugPrint(response)
                    if response.result.isSuccess {
                    self?.serverRequestResult(ServerResult.Success(response.data))
                    }
                    else{
                        self?.serverRequestResult(ServerResult.Failure(response.result.error))
                    }

            }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment