Alamofire를 사용하여 매개 변수가있는 파일 업로드


95

을 (를) 사용하여 파일을 업로드하려고합니다 Alamofire. 파일 ( NSUrl)을 사용하면 업로드가 잘 작동 하지만 NSData옵션 을 사용하는 방법을 알아낼 수 없습니까?

이것은 내가 테스트로 가지고있는 것입니다.

 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를 받고 있습니까?

또한 업로드시 추가 매개 변수를 어떻게 전송할 수 있습니까?

감사

편집하다

올바른 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)
}

여전히 업로드와 함께 추가 매개 변수를 보내는 방법을 알 수 없습니다.


"multipartFormData.appendBodyPart (data : image1Data, name :"file ", fileName :"myImage.png ", mimeType :"image / png ")"를 사용합니다. 그렇지 않으면 "문자 0 주위에 잘못된 값"오류가 발생합니다.
Avijit Nagare

답변:


81

다음은 대상 업로드 URL, 매개 변수 및 imageData를 요구하고 Alamofire.upload가 매개 변수와 함께 이미지를 업로드하는 데 필요한 URLRequestConvertible 및 NSData를 반환하는 간단한 함수입니다.

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

그리고 대상 URL에 대한 php 파일이 필요한 경우 (동일한 디렉토리에 'uploads'폴더 포함) :

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

안녕하세요, 저는 이미이 방법을 사용하고 있고 잘 작동합니다.하지만 서버 측에서는 요청 내용 유형 JSON을 변경합니다. 그 후이 방법이 작동하지 않습니다. 데이터를 json으로 업로드하고 싶습니다. 제발 도와주세요
mychar

1
거의 맞습니다, uploadData.appendData ( "Content-Disposition : form-data; name = \"file \ "; filename = \"file.png \ "\ r \ n".dataUsingEncoding (NSUTF8StringEncoding)!) in this line name = \ "file \", 실제로 file은 종이 클립과 같이 server ..에서 처리 할 키 이름입니다.
Albert.Qing

광산은 이전에 작동했고 지금은 NSCocoaErrorDomain 코드 3840을 받고 있는데, 누구든지이 문제를 해결 했습니까?
대부

@antiblank이 코드를 공유 해주셔서 감사합니다. 사용자가 내 웹 서비스 호출에서 사진을 업로드할지 여부를 선택할 수 있으므로 사진 매개 변수에 대해 NSData 또는 null을 허용 할 수 있도록이 함수를 변경하는 방법을 조언 해 주시겠습니까? 정의에서 NSData 대신 anyObject를 사용할 수 있습니까?
user2363025

3
헤더를 포함하여 어떻게 할 수 있습니까?
Poonam 2015

73

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

현재 신속한 버전 : https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server


let imageData = UIImageJPEGRepresentation (image, 1) {multipartFormData.append (imageData, withName : "file", fileName : "file.png", mimeType : "image / png")} for 파라미터 (키 값)} {multipartFormData.append ((.DATA 값 (사용 : .utf8))! withName 키?)}
라비 Ojha

1
이 경우 작동하지 않습니다 parameters입니다 [String:Any]때문에 value.data(using: .utf8))!유효하지 않습니다 Any Type. 이 문제를 해결하는 방법에 대한 제안이 있습니까?
Chlebta

57

다음은 antiblanks 답변을 기반으로 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)
                }
        })

이 업로드를 취소하는 방법은 무엇입니까? 다른 답변에서 나는 사람들이 var에 업로드를 assing한다고 말하는 것을 보았지만 그렇게 할 때 유형은 ()로 추론되므로 메서드를 호출 할 수 없습니까? 감사.
Sean Lintern

@ SeanLintern88 : request-Object에서 cancel ()을 호출 할 수 있습니다. 같은 것 : upload.cancel (). request-Object를 변수에 할당하고 cancel ()을 호출 할 수 있습니다.
EdFunke

1
case .Success(let upload, _, _) upload찾을 수 없습니다. 내가 뭔가를 놓치고 있습니까?
fatihyildizhan

@fatihyildizhan encodingResultMultipartFormDataEncodingResult열거 형입니다. 는 .Success Case(다음 매개 변수가 있습니다 request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) 그래서이 upload요청입니다. 추가 했습니까 import Alamofire?
EdFunke

이것으로 어떻게 진행을 유지합니까?
hris.to

10

Swift 2.2 Alamofire 3.3.1에 대한 EdFunke의 답변 향상

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

멀티 파트 업로드는 Alamofire의 다음 (1.3.0) 릴리스에 포함될 예정입니다. 그 동안이 스레드의 정보를 사용하여 파일 업로드를 단순화하고 하나 이상의 파일과 함께 요청에 추가 매개 변수 (일반 "입력")를 포함하는 클래스를 만들었습니다. 파일이 특정 유형이거나 라우터를 사용한다고 가정하지 않습니다.

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


안녕하세요, 귀하의 사례에서 업로드 프로세스의 성공 또는 오히려 실패를 iOS 측에서 확인할 수있는 방법이 있습니까? 대답 해줘서 고마워.
Zigii Wong

네, 물론입니다. 앞서 언급했듯이 uploadFile (request) 메서드는 Alamofire.request 메서드와 마찬가지로 Request 객체를 반환하므로 진행률 및 / 또는 응답 종료를 간단히 연결할 수 있습니다. 예 : fileUploader.uploadFile (request : request) .response {(request, response, data, error) in ....}
ncerezo

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)

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

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

?>

당신이 어떤 변화를했는지 말하면 좋을 것입니다. @antiblank의 답변을 편집 할 수있는 간단한 개선 이었습니까?
Luís Cruz

3
안녕하세요 milz, 예 @antiblank 답변에서 몇 가지 변경 사항, 코드는 저에게 매우 도움이됩니다. 감사합니다
Vincent Yan

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

@TomoMatsumotto 귀하의 코드를 사용하려고했을 때 "Use of unresolved identifier 'Router'"라는 오류가 발생했습니다. 라우터가 여기에서 사용중인 열거 형이라고 생각합니다. 답변을 업데이트 해 주시겠습니까? Thankz
Ankahathara 2015-04-02

@Ankahathara Router 열거 형을 만들거나 Router를 사용하는 대신 수동으로 NSURLRequest를 만듭니다. github.com/Alamofire/Alamofire

2

멀티 파트 요청을 수동으로 구성하는 방법을 조언하는 다른 답변이 있지만 AFNetworking을 계속 사용하는 것이 좋습니다. Objective-C로 작성되었지만 Swift 프로젝트에서 계속 사용할 수 있습니다 ( 같은 프로젝트의 Swift 및 Objective-C 참조 ). 어쨌든 AFNetworking을 사용하여 멀티 파트 요청을 제출하는 Swift 코드는 다음과 같습니다.

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메소드 또는 매개 변수 의 일반적인 편집기 코드 완성을 즐기지 못하지만 컴파일하고 실행하면 제대로 작동합니다.


이것은 좋은 지적이지만 "수동"부분이 Alamofire 3에서 다소 작다고 생각합니다. 위의 답변을 참조하십시오 (아래). stackoverflow.com/a/34961720/8047 ... 감사합니다
Dan Rosenstark

1

요청에 콘텐츠 유형 이 누락되어 415를 받고 있습니다. 아래는 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)")
        }
    }
}
}

0

아래는 신속하고 Php 코드입니다.

Swift 코드-> Apple Swift 버전 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1) 대상 : 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)

매개 변수 및 파일을 가져 오는 PHP 코드

여기 매개 변수는 $ _Request의 핸들입니다.

그리고 파일은 $ _File에서 처리됩니다.

$ _File data (Array, Dictionary 또는 String)의 형식은 swift side의 Request에 따라 달라집니다. Here See this line in code

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

PHP 측 withName : "imgFiles []"는 이름, 형식, 유형의 배열을 제공합니다.

"name": [ "06748B86-478E-421B-8470-6262755AC149.jpeg", "E70269E9-FB54-4BFD-B807-7E418C81540D.jpeg"], "type": [ "image / jpeg", "image / jpeg" ], "tmp_name": [ "/ tmp / phpz3UAPq", "/ tmp / phpCAPExG"], "오류": [0,0], "크기": [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);
            }

-2

나는 antiblank의 대답을 가져 와서 완료 핸들러를 사용하여 하나의 함수로 모두 포장했습니다. 누군가에게 유용 할 것이라고 생각했습니다. 나는 단순히 PHP 파일 (JSON이 아님)에서 문자열 응답을 취하기 때문에 약간 '거친'한 다음 antiblank의 대답입니다.

이름은 다음과 같습니다.

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";
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.