Tải lên tệp với các tham số bằng Alamofire


95

Tôi đang cố gắng tải lên một tệp bằng cách sử dụng Alamofire. Tải lên hoạt động tốt khi sử dụng Tệp ( NSUrl), tuy nhiên, tôi dường như không thể tìm ra cách sử dụng NSDatatùy chọn?

Đây là những gì tôi có như một bài kiểm tra:

 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)
 }

Tôi nhận được mã trạng thái 415?

Ngoài ra, làm cách nào để gửi qua các thông số bổ sung trong quá trình tải lên?

Cảm ơn

BIÊN TẬP

Tôi không đặt đúng Loại-Nội dung:

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)
}

Vẫn không thể tìm ra cách gửi các thông số bổ sung cùng với tải lên.


Sử dụng "multiartFormData.appendBodyPart (data: image1Data, name:" file ", fileName:" myImage.png ", mimeType:" image / png ")" nếu không sẽ gặp lỗi "Giá trị không hợp lệ xung quanh ký tự 0"
Avijit Nagare

Câu trả lời:


81

Đây là một hàm đơn giản yêu cầu url tải lên đích, các tham số và imageData và trả về URLRequestConvertible và NSData mà Alamofire.upload yêu cầu để tải lên một hình ảnh có các tham số.

// 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)
}    

Dưới đây là một ví dụ về cách sử dụng nó (xem TẠO VÀ GỬI YÊU CẦU):

// 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)")
}    

Và nếu bạn cần tệp php cho url đích (với thư mục 'tải lên' trong cùng thư mục):

// 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);

Xin chào, tôi đã sử dụng phương pháp này và hoạt động tốt, nhưng ở phía máy chủ, họ thay đổi loại nội dung yêu cầu JSON. Sau đó phương thức này không hoạt động. Tôi muốn tải lên dữ liệu dưới dạng json ... bạn có thể vui lòng giúp tôi không
mychar

1
gần đúng, uploadData.appendData ("Content-Disposition: form-data; name = \" file \ "; filename = \" file.png \ "\ r \ n" .dataUsingEncoding (NSUTF8StringEncoding)!) trong tên dòng này = \ "file \", thực sự tệp là tên khóa mà máy chủ sẽ xử lý..như kẹp giấy.
Albert.Qing

Mines đã hoạt động trước đây và bây giờ tôi nhận được mã NSCocoaErrorDomain 3840, có ai đã giải quyết vấn đề này không?
Bố già

@antiblank cảm ơn bạn đã chia sẻ mã này. Bạn có thể cho tôi biết làm thế nào để thay đổi chức năng này để nó có thể chấp nhận NSData hoặc null cho tham số hình ảnh vì người dùng có tùy chọn tải lên hình ảnh trong lệnh gọi dịch vụ web của tôi hay không. Tôi có thể sử dụng anyObject thay vì NSData trong định nghĩa
user2363025

3
làm thế nào chúng ta có thể làm điều này bao gồm cả tiêu đề?
Poonam

73

Tải lên ảnh / tệp với các thông sốtiêu đề tùy chỉnh thông qua Swift 3 & 4 và 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)")
          }
  })
}

thông qua Swift 2 và 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)
        }
    })
  }

Phiên bản nhanh hiện tại: https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server


bất kỳ cơ quan nào có thể cho tôi biết về những dòng bên dưới này không nếu let imageData = UIImageJPEGRepresentation (image, 1) {MultiartFormData.append (imageData, withName: "file", fileName: "file.png", mimeType: "image / png")} cho (khóa, giá trị) trong các tham số {MultiartFormData.append ((value? .data (using: .utf8)) !, withName: key)}}
Ravi Ojha

1
Điều này sẽ không hoạt động nếu parameters[String:Any]value.data(using: .utf8))!không hợp lệ cho Any Type. Bạn có gợi ý làm thế nào để giải quyết điều này?
Chlebta

57

Đây là một Giải pháp sử dụng Alamofire 3.0 dựa trên câu trả lời kháng thể:

 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)
                }
        })

Bạn sẽ làm thế nào về việc hủy tải lên này? Trong các câu trả lời khác, tôi thấy mọi người nói với việc tải lên một var nhưng khi tôi làm điều đó thì kiểu được suy ra là (), do đó không cho phép các phương thức được gọi trên nó? Cảm ơn.
Sean Lintern

@ SeanLintern88: Bạn có thể gọi hủy () theo yêu cầu-Đối tượng. Một cái gì đó như: upload.cancel (). Bạn có thể gán theo yêu cầu-Object để một biến và kêu gọi hủy bỏ ()
EdFunke

1
case .Success(let upload, _, _) uploadkhông thể tìm thấy. Tui bỏ lỡ điều gì vậy?
fatihyildizhan

@fatihyildizhan encodingResultlà một MultipartFormDataEncodingResultenum. Có .Success Casecác tham số sau: ( request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) uploadYêu cầu cũng vậy. Bạn đã thêm import Alamofire?
EdFunke

Làm thế nào để bạn tiếp tục tiến bộ với điều này?
hris.to

10

Cải thiện câu trả lời của EdFunke cho Swift 2.2 Alamofire 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)
                }
            }
        )

4

Tải lên nhiều phần dự kiến ​​sẽ được đưa vào bản phát hành tiếp theo (1.3.0) của Alamofire. Trong thời gian chờ đợi, bằng cách sử dụng thông tin trong chuỗi này, tôi đã tạo một lớp giúp đơn giản hóa việc tải lên tệp và bao gồm các tham số bổ sung ("đầu vào" thông thường) trong yêu cầu cùng với một hoặc nhiều tệp. Mà không cần giả định rằng các tệp thuộc một loại cụ thể hoặc sử dụng Bộ định tuyến.

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 )
  }

}

Nó sẽ được sử dụng như thế này:

// 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)

Hãy xem hoặc tải xuống từ ý chính này: https://gist.github.com/ncerezo/b1991f8dfac01cb162c0


Xin chào, có cách nào để kiểm tra quá trình tải lên thành công hay đúng hơn là thất bại ở phía iOS, trong trường hợp ví dụ của bạn không? Cảm ơn vì đã trả lời.
Zigii Wong,

Phải, tất nhiên. Như tôi đã đề cập, phương thức uploadFile (request) trả về một đối tượng Request, giống như phương thức Alamofire.request, vì vậy bạn có thể chỉ cần đóng chuỗi tiến trình và / hoặc phản hồi. Ví dụ: fileUploader.uploadFile (request: request) .response {(request, response, data, error) in ....}
ncerezo

3

Mã trong câu trả lời của @ kháng thể không hoạt động đối với tôi. Tôi đã thực hiện một vài thay đổi và hiện nó đang hoạt động:

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)
}

SỬ DỤNG:

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 từ https://github.com/nghialv/Net/blob/master/Net/NetData.swift

Mã 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 );  

?>

Sẽ rất tốt nếu bạn nói rõ bạn đã thực hiện thay đổi gì. Đó có phải là một cải tiến đơn giản có thể là một chỉnh sửa cho câu trả lời của @ kháng thể không?
Luís Cruz

3
Xin chào milz, có chỉ là một vài thay đổi từ câu trả lời @antiblank, mã giúp tôi rất nhiều. Cảm ơn
Vincent Yan

2

Phiên bản ngắn hơn dựa trên câu trả lời @antiblank và @VincentYan.

Lớp học

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)
    }
}

Sử dụng

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)
    }

@TomoMatsumotto Khi tôi cố gắng sử dụng mã của bạn, tôi gặp lỗi có tên "Sử dụng mã định danh chưa được giải quyết 'Bộ định tuyến'", tôi nghĩ Bộ định tuyến là một enum bạn đang sử dụng ở đây. Bạn có thể vui lòng cập nhật câu trả lời? Thankz
Ankahathara

@Ankahathara Hoặc tạo một enum Bộ định tuyến hoặc tạo thủ công NSURLRequest thay vì sử dụng Bộ định tuyến. github.com/Alamofire/Alamofire
Tom

2

Mặc dù có những câu trả lời khác hướng dẫn cách tạo các yêu cầu nhiều phần theo cách thủ công, bạn có thể chỉ muốn gắn bó với AFNetworking. Mặc dù nó được viết bằng Objective-C, bạn vẫn có thể sử dụng nó trong các dự án Swift của mình (xem Swift và Objective-C trong cùng một dự án ). Dù sao, mã Swift để gửi yêu cầu nhiều phần bằng AFNetworking như sau:

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 gây khó chịu có vấn đề khi nhận dạng id<AFMultipartFormData>tham số này formData, vì vậy bạn không thích hoàn thành mã trình soạn thảo điển hình của appendPartWithFileDataphương thức hoặc các tham số của nó, nhưng khi bạn biên dịch và chạy nó, nó hoạt động tốt.


Đây là một điểm tốt, nhưng tôi nghĩ rằng "thủ công" mảnh có phần nhỏ hơn trong Alamofire 3. Xem câu trả lời này trên (dưới đây): stackoverflow.com/a/34961720/8047 ... Cảm ơn
Dan Rosenstark

1

Bạn nhận được 415 vì thiếu loại nội dung trong yêu cầu của bạn. Dưới đây là tổng số cảnh báo khi tải lên hình ảnh trên Swift 2 và 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)")
        }
    }
}
}

0

Dưới đây là mã nhanh và mã Php

Mã Swift -> Apple Swift phiên bản 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1) Mục tiêu: x86_64-apple-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)

Mã PHP để lấy các thông số và tệp

Tại đây Các thông số được xử lý trong $ _Request

Và Tệp được xử lý trong $ _File

Định dạng trong dữ liệu $ _File (Mảng, Từ điển hoặc Chuỗi) sẽ phụ thuộc vào Yêu cầu ở phía nhanh, Tại đây Xem dòng này trong mã

MultiartFormData.append (data, withName: "imgFiles []", fileName: "(NSUUID (). uuidString) .jpeg", mimeType: "image / jpeg")

trong Php side withName: "imgFiles []" cung cấp mảng tên, định dạng, Loại

Ví dụ

"name": ["06748B86-478E-421B-8470-6262755AC149.jpeg", "E70269E9-FB54-4BFD-B807-7E418C81540D.jpeg"], "type": ["image / jpeg", "image / jpeg" ], "tmp_name": ["/ tmp / phpz3UAPq", "/ tmp / phpCAPExG"], "error": [0,0], "size": [2779495,2067259]}

Mã 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);
            }

-2

Tôi đã lấy câu trả lời của kháng thể và gói tất cả điều này trong 1 hàm với trình xử lý hoàn thành. Nghĩ rằng nó có thể hữu ích cho ai đó. Đó là một chút 'khó khăn hơn' sau đó câu trả lời của immulank vì tôi chỉ đơn giản là lấy một chuỗi phản hồi từ tệp PHP (không phải JSON).

Đây là cách bạn gọi nó:

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
    }

Đây là chức năng của chính nó:

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)

            }
        }
    )
}

Và đây là tập tin 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";
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.