2014-09-30 3 views
80

Я пытаюсь загрузить файл, используя Alamofire. Загрузка работает отлично при использовании файла (NSUrl), однако я не могу понять, как использовать опцию NSData?Загрузка файла с параметрами с использованием Alamofire

Это то, что я как тест:

var url:NSURL = NSURL.URLWithString("http://localhost:8080/bike.jpeg") 

var err: NSError? 
var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err) 

Alamofire.upload(.POST, "http://localhost:8080/rest/service/upload/test.png", imageData) 
     .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 
      println(totalBytesWritten) 
     } 
     .responseJSON { (request, response, JSON, error) in 
      println(request) 
      println(response) 
      println(JSON) 
} 

я получаю код состояния 415?

Также, как я могу отправить через дополнительные параметры в загрузке?

Благодаря

EDIT

Я не заходило правильный Content-Type:

var manager = Manager.sharedInstance 
manager.session.configuration.HTTPAdditionalHeaders = ["Content-Type": "application/octet-stream"] 


let imageData: NSMutableData = NSMutableData.dataWithData(UIImageJPEGRepresentation(imageTest.image, 30)); 

Alamofire.upload(.POST, "http://localhost:8080/rest/service/upload?attachmentName=file.jpg", imageData) 
     .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 
      println(totalBytesWritten) 
     } 
     .responseString { (request, response, JSON, error) in 
      println(request) 
      println(response) 
      println(JSON) 
} 

Тем не менее не могу понять, как отправить дополнительные параметры вместе с загрузкой.

+0

Используйте «multipartFormData.appendBodyPart» (данные: image1Data, name: «file», fileName: «myImage.png», mimeType: «image/png») »this is imp иначе получить ошибку« Недопустимое значение вокруг символа 0 » –

ответ

77

Вот простая функция, которая требует целевого URL-адреса загрузки, параметров и изображений и возвращает URLRequestConvertible и NSData, которые Alamofire.upload требует для загрузки изображения с параметрами.

// this function creates the required URLRequestConvertible and NSData we need to use Alamofire.upload 
func urlRequestWithComponents(urlString:String, parameters:Dictionary<String, String>, imageData:NSData) -> (URLRequestConvertible, NSData) { 

    // create url request to send 
    var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!) 
    mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue 
    let boundaryConstant = "myRandomBoundary12345"; 
    let contentType = "multipart/form-data;boundary="+boundaryConstant 
    mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type") 



    // create upload data to send 
    let uploadData = NSMutableData() 

    // add image 
    uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    uploadData.appendData(imageData) 

    // add parameters 
    for (key, value) in parameters { 
     uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!) 
    } 
    uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 



    // return URLRequestConvertible and NSData 
    return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData) 
}  

Вот пример того, как использовать его (см СОЗДАТЬ И ОТПРАВИТЬ ЗАПРОС):

// init paramters Dictionary 
var parameters = [ 
    "task": "task", 
    "variable1": "var" 
] 

// add addtionial parameters 
parameters["userId"] = "27" 
parameters["body"] = "This is the body text." 

// example image data 
let image = UIImage(named: "177143.jpg") 
let imageData = UIImagePNGRepresentation(image) 



// CREATE AND SEND REQUEST ---------- 

let urlRequest = urlRequestWithComponents("http://example.com/uploadText/", parameters: parameters, imageData: imageData) 

Alamofire.upload(urlRequest.0, urlRequest.1) 
    .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 
     println("\(totalBytesWritten)/\(totalBytesExpectedToWrite)") 
    } 
    .responseJSON { (request, response, JSON, error) in 
     println("REQUEST \(request)") 
     println("RESPONSE \(response)") 
     println("JSON \(JSON)") 
     println("ERROR \(error)") 
}  

И если вам нужен файл PHP для целевого URL (с папкой «загрузки» в тот же каталог):

// get picture variables 
$file  = $_FILES['file']['tmp_name']; 
$fileName = $_FILES['file']['name']; 
$fileType = $_FILES['file']['type']; 

// check extension 
$allowedExts = array("jpg", "jpeg", "png"); 
$rootName = reset(explode(".", $fileName)); 
$extension = end(explode(".", $fileName)); 

// create new file name 
$time = time(); 
$newName = $rootName.$time.'.'.$extension; 

// temporarily save file 
$moved = move_uploaded_file($_FILES["file"]["tmp_name"], "uploads/".$newName); 
if ($moved) $path = "uploads/".$newName; 

$body = $_POST['body']; 
$userId = $_POST['userId']; 


$time = time(); 
if ($moved) { 
    $fullUrl = "http://antiblank.com/testPhotoUpload/".$path; 
    $arrayToSend = array('status'=>'success','time'=>$time,'body'=>$body,'userId'=>$userId, "imageURL"=>$fullUrl); 
} else { 
    $arrayToSend = array('status'=>'FAILED','time'=>$time,'body'=>$body,'userId'=>$userId); 
} 

header('Content-Type:application/json'); 
echo json_encode($arrayToSend); 
+0

Привет, я уже использую этот метод и хорошо работает. Но на стороне сервера они меняют тип запроса запроса JSON. После этого этот метод не работает. Я хочу загрузить данные как json ... Можете ли вы, пожалуйста, помочь мне – mychar

+2

Это не похоже, работают в iOS 8. У кого-нибудь еще есть проблемы в iOS 8 с этим? – Tyler

+1

почти справа, uploadData.appendData («Content-Disposition: form-data; name = \" file \ "; filename = \" file.png \ "\ r \ n" .dataUsingEncoding (NSUTF8StringEncoding)!) В этом имени строки = \ "file \", действительно файл - это ключевое имя, которое будет обрабатываться сервером .. например, paperclip. –

3

Код в ответе @ antiblank не работал на меня. Я сделал несколько изменений, и теперь он работает:

func urlRequestWithComponents(urlString:String, parameters:NSDictionary) -> (URLRequestConvertible, NSData) { 

    // create url request to send 
    var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!) 
    mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue 
    //let boundaryConstant = "myRandomBoundary12345" 
    let boundaryConstant = "NET-POST-boundary-\(arc4random())-\(arc4random())" 
    let contentType = "multipart/form-data;boundary="+boundaryConstant 
    mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type") 


    // create upload data to send 
    let uploadData = NSMutableData() 

    // add parameters 
    for (key, value) in parameters { 

     uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

     if value is NetData { 
      // add image 
      var postData = value as NetData 


      //uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(postData.filename)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

      // append content disposition 
      var filenameClause = " filename=\"\(postData.filename)\"" 
      let contentDispositionString = "Content-Disposition: form-data; name=\"\(key)\";\(filenameClause)\r\n" 
      let contentDispositionData = contentDispositionString.dataUsingEncoding(NSUTF8StringEncoding) 
      uploadData.appendData(contentDispositionData!) 


      // append content type 
      //uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) // mark this. 
      let contentTypeString = "Content-Type: \(postData.mimeType.getString())\r\n\r\n" 
      let contentTypeData = contentTypeString.dataUsingEncoding(NSUTF8StringEncoding) 
      uploadData.appendData(contentTypeData!) 
      uploadData.appendData(postData.data) 

     }else{ 
      uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!) 
     } 
    } 
    uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 



    // return URLRequestConvertible and NSData 
    return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData) 
} 

ПРИМЕНЕНИЕ:

let docDir:AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] 
let imagePath = docDir + "/myPic.jpg" 

var imageData = NSData(contentsOfFile: imagePath, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil) 
var parameters = [ 
      "pic"   :NetData(nsData: imageData!, filename: "customName.jpg"), 
      "otherParm"  :"Value" 
     ] 


    let urlRequest = self.urlRequestWithComponents("http://www.example.com/upload.php", parameters: parameters) 

NetData от https://github.com/nghialv/Net/blob/master/Net/NetData.swift

upload.php Код:

<?php 
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead 
// of $_FILES. 

$uploaddir = 'uploads/'; 
// PS: custom filed name : pic 
$uploadfile = $uploaddir . basename($_FILES['pic']['name']); 

if (move_uploaded_file($_FILES['pic']['tmp_name'], $uploadfile)) { 
    $array = array ("code" => "1", "message" => "successfully"); 
} else { 
    $array = array ("code" => "0", "message" => "Possible file upload attack!".$_FILES['pic']['name']); 
} 

echo json_encode ($array); 

?> 
+0

Было бы неплохо, если бы вы заявили, какие изменения вы сделали. Было ли это простое улучшение, которое могло бы быть результатом редактирования ответа @ antiblank? –

+3

Привет, milz, да только несколько изменений от ответа @antiblank, код мне очень помогает. Спасибо –

2

укороченная версия на основе ответов @antiblank и @VincentYan.

Класс

class Photo { 
    class func upload(image: UIImage, filename: String) -> Request { 
     let route = Router.CreatePhoto() 
     var request = route.URLRequest.mutableCopy() as NSMutableURLRequest 
     let boundary = "NET-POST-boundary-\(arc4random())-\(arc4random())" 
     request.setValue("multipart/form-data;boundary="+boundary, 
         forHTTPHeaderField: "Content-Type") 

     let parameters = NSMutableData() 
     for s in ["\r\n--\(boundary)\r\n", 
        "Content-Disposition: form-data; name=\"photos[photo]\";" + 
        " filename=\"\(filename)\"\r\n", 
        "Content-Type: image/png\r\n\r\n"] { 
      parameters.appendData(s.dataUsingEncoding(NSUTF8StringEncoding)!) 
     } 
     parameters.appendData(UIImageJPEGRepresentation(image, 1)) 
     parameters.appendData("\r\n--\(boundary)--\r\n" 
           .dataUsingEncoding(NSUTF8StringEncoding)!) 
     return Alamofire.upload(request, parameters) 
    } 
} 

Использование

let rep = (asset as ALAsset).defaultRepresentation() 
let ref = rep.fullResolutionImage().takeUnretainedValue() 
Photo.upload(UIImage(CGImage: ref)!, filename: rep.filename()) 
    .progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in 
     println(totalBytesWritten) 
    } 
    .responseJSON { (request, response, JSON, error) in 
     println(JSON) 
    } 
+0

@TomoMatsumotto Когда я попытался использовать ваш код, я получаю сообщение об ошибке «Использование неразрешенного идентификатора« Router », я думаю, что маршрутизатор - это перечисление, которое вы используете здесь. Не могли бы вы обновить ответ? Thankz – Ankahathara

+0

@Ankahathara Либо создайте перечисление маршрутизатора, либо вручную создайте NSURLRequest вместо использования Router. https://github.com/Alamofire/Alamofire –

-2

Я принял ответ antiblank и обернут все это в 1 функции с обработчиком завершения. Думал, что это может быть полезно для кого-то. Это немного «грубее», а затем ответ антикланка, поскольку я просто беру строковый ответ из файла PHP (а не JSON).

Вот как вы это называете:

let imageData = UIImagePNGRepresentation(myImageView.image) 

uploadImage("http://www.example.com/image_upload.php", imageData: imageData, subdir: "images", filename: "imageID.png") 
    { (req, res, str, err) -> Void in 
     // do whatever you want to to for error handling and handeling success 
    } 

Вот сама функция:

func uploadImage(urlToPHPFile: String, imageData: NSData, subdir: String, filename: String, completionHandler:(request:NSURLRequest, response:NSURLResponse?, responseString:String?, error: NSError?) ->()) { 

    func urlRequestWithComponents(urlString:String, parameters:Dictionary<String, String>, imageData:NSData) -> (URLRequestConvertible, NSData) { 
     // create url request to send 
     var mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!) 
     mutableURLRequest.HTTPMethod = Method.POST.rawValue 
     let boundaryConstant = "myRandomBoundary12345"; 
     let contentType = "multipart/form-data;boundary="+boundaryConstant 
     mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type") 

     // create upload data to send 
     let uploadData = NSMutableData() 

     // add image 
     uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     uploadData.appendData(imageData) 

     // add parameters 
     for (key, value) in parameters { 
      uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
      uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!) 
     } 
     uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

     // return URLRequestConvertible and NSData 
     return (ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData) 
    } 

    let parameters = [ 
     "subdir" : subdir, 
     "filename": filename 
    ] 
    let urlRequest = urlRequestWithComponents(urlToPHPFile, parameters, imageData) 

    AlamoFire.upload(urlRequest.0, urlRequest.1) 
     .responseString(completionHandler: { [weak self] (req, res, str, err) -> Void in 
      if let strongSelf = self { 
       completionHandler(request: req, response: res, responseString: str, error: err) 

      } 
     } 
    ) 
} 

А вот файл PHP.

$subdir = $_POST['subdir']; 
$filename = $_POST["filename"]; 

$targetPath = $subdir.'/'.$filename; 

$moved = move_uploaded_file($_FILES["file"]["tmp_name"], $targetPath); 
if ($moved) { 
    echo "OK"; 
} 
else { 
    echo "Error: file not uploaded"; 
} 
2

Хотя существуют и другие ответы, которые консультируют, как вручную построить многокомпонентные запросы, вы просто можете придерживаться AFNetworking. Несмотря на то, что он написан в Objective-C, вы все равно можете использовать его в своих проектах Swift (см. Swift and Objective-C in the Same Project). Во всяком случае, Swift код представить многослойный запрос с использованием AFNetworking выглядит следующим образом:

let data = UIImagePNGRepresentation(image) 

let manager = AFHTTPSessionManager() 

manager.POST(uploadURLString, parameters: nil, constructingBodyWithBlock: { formData in 
    formData.appendPartWithFileData(data, name: "image", fileName: "test.png", mimeType: "image/png") 
}, success: { operation, responseObject in 
    println(responseObject) 
}) { operation, error in 
    println(error) 
} 

Xcode раздражающих имеют проблемы, признающие этот id<AFMultipartFormData> параметр, formData, так что вам не нравится типичный завершение редактор кода метод appendPartWithFileData или его параметры, но когда вы его компилируете и запускаете, он работает нормально.

+0

Это хороший момент, но я думаю, что «ручной» кусок несколько меньше в Alamofire 3. См. этот ответ выше (ниже): http://stackoverflow.com/ a/34961720/8047 ... Спасибо –

4

Многостраничная загрузка планируется включить в следующую (1.3.0) версию Alamofire. Тем временем, используя информацию в этом потоке, я создал класс, который упрощает загрузку файлов и включает в себя дополнительные параметры (обычные «входы») в запросе вместе с одним или несколькими файлами. Не предполагая, что файлы имеют определенный тип или использование маршрутизаторов.

FileUploader.swift:

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) 

Проверьте это или скачать с этой сутью: https://gist.github.com/ncerezo/b1991f8dfac01cb162c0

+0

Привет, есть ли способ проверить успешность процесса загрузки или, скорее, сбой на стороне iOS, в вашем примере? Спасибо за ответ. –

+0

Да, конечно. Как я уже упоминал, метод uploadFile (запрос) возвращает объект Request, как и метод Alamofire.request, поэтому вы можете просто проследить прогресс и/или закрыть ответ. Например: fileUploader.uploadFile (запрос: запрос) .response {(запрос, ответ, данные, ошибка) в ....} – ncerezo

55

Вот решение с использованием Alamofire 3,0 основанный на антибактериальных средствах ответ:

let parameters = [ 
      "par1": "value", 
      "par2": "value2"]  

let URL = "YOUR_URL.php" 

let image = UIImage(named: "image.png") 

Alamofire.upload(.POST, URL, multipartFormData: { 
       multipartFormData in 

       if let _image = image { 
        if let imageData = UIImageJPEGRepresentation(_image, 0.5) { 
         multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: "file.png", mimeType: "image/png") 
        } 
       } 

       for (key, value) in parameters { 
        multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key) 
       } 

      }, encodingCompletion: { 
       encodingResult in 

       switch encodingResult { 
       case .Success(let upload, _, _): 
        upload.responseObject { (response: Response<UploadData, NSError>) -> Void in 

        switch response.result { 
        case .Success: 
         completionHandler?(success: true) 
        case .Failure(let error): 
         completionHandler?(success: false) 
        } 

       } 
       case .Failure(let encodingError): 
        print(encodingError) 
       } 
     }) 
+0

Как бы вы отказались от этой загрузки? В других ответах я вижу, как люди говорят, чтобы загрузить загрузку в var, но когда я делаю, что тип выводится как(), таким образом, не позволяя вызовам на него? Благодарю. – SeanLintern88

+0

@ SeanLintern88: Вы можете вызвать cancel() для объекта request. Что-то вроде: upload.cancel(). Вы можете назначить запрос-объект переменной и отменить вызов() – EdFunke

+1

'case .Success (let upload, _, _)' 'upload' не может найти. Я что-то упускаю? – fatihyildizhan

61

Загрузить фото/Файл с параметрами и пользовательских заголовков через Swift 3 & 4 и Alamofire 4

// import Alamofire 
func uploadWithAlamofire() { 
    let image = UIImage(named: "bodrum")! 

    // define parameters 
    let parameters = [ 
    "hometown": "yalikavak", 
    "living": "istanbul" 
    ] 

    Alamofire.upload(multipartFormData: { multipartFormData in 
    if let imageData = UIImageJPEGRepresentation(image, 1) { 
     multipartFormData.append(imageData, withName: "file", fileName: "file.png", mimeType: "image/png") 
    } 

    for (key, value) in parameters { 
     multipartFormData.append((value?.data(using: .utf8))!, withName: key) 
    }}, to: "upload_url", method: .post, headers: ["Authorization": "auth_token"], 
     encodingCompletion: { encodingResult in 
      switch encodingResult { 
      case .success(let upload, _, _): 
      upload.response { [weak self] response in 
       guard let strongSelf = self else { 
       return 
       } 
       debugPrint(response) 
      } 
      case .failure(let encodingError): 
      print("error:\(encodingError)") 
      } 
    }) 
} 

через Swift 2 и Alamofire 3

// import Alamofire 
    func uploadWithAlamofire() { 
    let image = UIImage(named: "myImage")! 

    // define parameters 
    let parameters = [ 
     "hometown": "yalikavak", 
     "living": "istanbul" 
    ] 

    // Begin upload 
    Alamofire.upload(.POST, "upload_url", 
     // define your headers here 
     headers: ["Authorization": "auth_token"], 
     multipartFormData: { multipartFormData in 

     // import image to request 
     if let imageData = UIImageJPEGRepresentation(image, 1) { 
      multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: "myImage.png", mimeType: "image/png") 
     } 

     // import parameters 
     for (key, value) in parameters { 
      multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key) 
     } 
     }, // you can customise Threshold if you wish. This is the alamofire's default value 
     encodingMemoryThreshold: Manager.MultipartFormDataEncodingMemoryThreshold, 
     encodingCompletion: { encodingResult in 
     switch encodingResult { 
     case .Success(let upload, _, _): 
      upload.responseJSON { response in 
      debugPrint(response) 
      } 
     case .Failure(let encodingError): 
      print(encodingError) 
     } 
    }) 
    } 
+2

Супер полезный, пожелал, чтобы была версия swift3, которую я могу прочитать. – Cmag

+0

У вас есть PHP-версия вашей быстрой загрузки? – imstillalive

+0

Извините, у меня его нет. @imstillalive – fatihyildizhan

1

Вы получив 415 из-за отсутствия типа контента в вашем req уесть. Ниже всего soution для загрузки изображений на Swift 2 и AlamoFire

import UIKit 
import Alamofire 

class ViewController: UIViewController { 

@IBOutlet var imageView: UIImageView! 
@IBOutlet var btnUpload: UIButton! 
override func viewDidLoad() { 
    super.viewDidLoad() 
} 

func successDataHandler(responseData:String){ 

    print ("IMAGE UPLOAD SUCCESSFUL !!!") 

} 

func failureDataHandler(errorData:String){ 

    print (" !!! IMAGE UPLOAD FAILURE !!! ") 

} 

@IBAction func actionUpload(sender: AnyObject) { 

    let URL = "http://m8coreapibeta.azurewebsites.net/api/cards/SaveImages" 

    let postDataProlife:[String:AnyObject] = ["CardId":(dataCardDetail?.userId)!,"ImageType":1,"ImageData":imageView.image!] 

    uplaodImageData(URL, postData: postDataProlife, successHandler: successDataHandler, failureHandler: failureDataHandler) 
} 

func uplaodImageData(RequestURL: String,postData:[String:AnyObject]?,successHandler: (String) ->(),failureHandler: (String) ->()) ->() { 

    let headerData:[String : String] = ["Content-Type":"application/json"] 

    Alamofire.request(.POST,RequestURL, parameters: postData, encoding: .URLEncodedInURL, headers: headerData).responseString{ response in 
     switch response.result { 
     case .Success: 
      print(response.response?.statusCode) 
      successHandler(response.result.value!) 
     case .Failure(let error): 
      failureHandler("\(error)") 
     } 
    } 
} 
} 
9

ответ ПОВЫШЕНИЕ EdFunke для Swift 2,2Alamofire 3,3.1

Alamofire.upload(.POST, urlString, multipartFormData: { 
      multipartFormData in 
      if let _image = self.profilePic.image { 
       if let imageData = UIImagePNGRepresentation(_image) { 
        multipartFormData.appendBodyPart(data: imageData, name: "user_image", fileName: "file.png", mimeType: "image/png") 
       } 
      } 
      for (key, value) in userInfo { 
       multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key) 
      } 
      }, encodingCompletion: { encodingResult in 
       switch encodingResult { 
       case .Success(let upload, _, _): 
        upload.responseJSON { response in 
         debugPrint(response) 
        } 
       case .Failure(let encodingError): 
        print(encodingError) 
       } 
      } 
     ) 
0

Ниже быстры и Php код

Swift код -> Apple, Swift версия 3.0.1 (swiftlang-800.0.58.6 лязг-800.0.42.1) Цель: x86_64-яблочно-macosx10. 9

class func upload(jsonObject: AnyObject , files : Array<Any>? = nil , completionHandler : CompletionBlock? = nil ,failureHandler : FailureBlock? = nil) 
{ 

    Alamofire.upload(multipartFormData: 
     { (multipartFormData) in 

      if let filesO = files 
      { 
       for i in (filesO.enumerated()) 
       { 
        let image = UIImage(named: "\(i.element)") 

        let data = UIImageJPEGRepresentation(image!, 1)! 

        multipartFormData.append(data, withName: "imgFiles[]" , fileName: "\(NSUUID().uuidString).jpeg" , mimeType: "image/jpeg") 
        // imgFiles[] give array in Php Side 
        // imgFiles will give string in PHP String 


       } 

      } 


      for (key, value) in jsonObject as! [String : String] 
      { 

       multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key) 

      }}   
    }, 
        to:baseURL) 

PHP код, чтобы получить параметры и файл

Здесь параметры являются ручки в $ _R Equest

и файлы ручка $ _file

Формат в данных $ _file (массив, словарь или строка) будет зависеть от запроса в быстрой стороне, вот видите эту строку в коде

multipartFormData. (добавить данные, withName: "imgFiles []", FileName: "(NSUUID() uuidString) .jpeg.", Mimetype: "изображение/JPEG")

в Php боковой withName: «imgFiles [] "дает массив имени, формата, тип

Например

"Название": [ "06748B86-478E-421B-8470-6262755AC149.jpeg", "E70269E9-FB54-4BFD-B807-7E418C81540D.jpeg"], "тип": [ «image/jpeg», «image/jpeg»], «tmp_name»: ["/ tmp/phpz3UAPq", "/ tmp/phpCAPExG"], "error": [0,0], "size": [ 2779495,2067259]}

PHP код

if (isset($_FILES['imgFiles']) and strlen($orderId) > 0) { 

     foreach ($_FILES['imgFiles']['tmp_name'] as $key => $tmp_name) { 

      $file_name = $key . $_FILES['imgFiles']['name'][$key]; 
      $file_size = $_FILES['imgFiles']['size'][$key]; 
      $file_tmp = $_FILES['imgFiles']['tmp_name'][$key]; 
      $file_type = $_FILES['imgFiles']['type'][$key]; 
if (is_dir("$desired_dir/" . $file_name) == false) { 
       //move_uploaded_file($file_tmp, "user_data/" . $file_name); 
       move_uploaded_file($file_tmp, $desired_dir . "/" . 
      $file_name); 
      } else {   //rename the file if another one exist 
       $new_dir = $desired_dir . "/" . $file_name . time(); 
       rename($file_tmp, $new_dir); 
      }