web-dev-qa-db-ja.com

alamofireで画像をアップロード

Alamofireを使用してサーバーに画像をアップロードしようとしていますが、コードが機能しません。これは私のコードです:

var parameters = ["image": "1.jpg"]
    let image = UIImage(named: "1.jpg")
    let imageData = UIImagePNGRepresentation(image)
    let urlRequest = urlRequestWithComponents("http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/", parameters: parameters, imageData: imageData)
    Alamofire.upload(urlRequest.0, data: 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)")
    }

これはurlRequestWithComponentsの方法です。

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

そしてこれは私がコンソールで得るものです:

リクエスト{URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ } RESPONSEオプション({URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ } {ステータスコード:200、ヘッダー{"Accept-Ranges" = bytes; Connection = close; "Content-Length" = 345; "Content-Type" = "text/html"; Date = "Tue、25 2015年8月10:52:01GMT ";"最終変更 "=" 2015年8月24日月曜日03:54:55GMT ";サーバー= Apache;}})JSON nil ERRORオプション(エラードメイン= NSCocoaErrorDomainコード= 3840"操作を完了できませんでした。(Cocoaエラー3840。) "(文字0周辺の値が無効です。)UserInfo = 0x7f8c68c1c130 {NSDebugDescription =文字0周辺の値が無効です。})

私のPHPコンテンツ:

<? php
echo $_FILES['image']['name'].
'<br/>';


//ini_set('upload_max_filesize', '10M');
//ini_set('post_max_size', '10M');
//ini_set('max_input_time', 300);
//ini_set('max_execution_time', 300);


$target_path = "uploads/";

$target_path = $target_path.basename($_FILES['image']['name']);

try {
  //throw exception if can't move the file
  if (!move_uploaded_file($_FILES['image']['tmp_name'], $target_path)) {
    throw new Exception('Could not move file');
  }

  echo "The file ".basename($_FILES['image']['name']).
  " has been uploaded";
} catch (Exception $e) {
  die('File did not upload: '.$e - > getMessage());
} ?>

私のコードはこの提案に従いました: Alamofireを使用してパラメータを含むファイルをアップロードする 。助けてください、ありがとう

8
user3087360

Rob's 正解ですが、これがSwift 2.0バージョンで、アップロードの進行状況更新。

次のコードをコピーして貼り付け、アップロードURLを変更して、パラメータを追加するだけです。チャームのように機能するはずです。

PS: MRProgress は進捗状況の更新のための素晴らしいライブラリです!

    let apiToken = "ABCDE"
    Alamofire.upload(
        .POST,
        "http://sample.com/api/upload",
        multipartFormData: { multipartFormData in
            multipartFormData.appendBodyPart(data: imageData, name: "yourParamName", fileName: "imageFileName.jpg", mimeType: "image/jpeg")
            multipartFormData.appendBodyPart(data: apiToken.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"api_token")
            multipartFormData.appendBodyPart(data: otherBodyParamValue.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name :"otherBodyParamName")
        },
        encodingCompletion: { encodingResult in
            switch encodingResult {
            case .Success(let upload, _, _):
                upload.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
                    print("Uploading Avatar \(totalBytesWritten) / \(totalBytesExpectedToWrite)")
                    dispatch_async(dispatch_get_main_queue(),{
                        /**
                        *  Update UI Thread about the progress
                        */
                    })
                }
                upload.responseJSON { (JSON) in
                    dispatch_async(dispatch_get_main_queue(),{
                        //Show Alert in UI
                        print("Avatar uploaded");
                    })
                }

            case .Failure(let encodingError):
                //Show Alert in UI
                print("Avatar uploaded");
            }
        }
    );
6
Jack Song

エラーは、応答が有効なJSONではないことを示しています。 responseJSONを呼び出しています。これは、JSON応答を期待しているが、サーバーコードがJSONを生成していないことを示しています。したがって、2つの解決策があります。

  1. PHPコードを変更して、JSON応答を生成することをお勧めします。

    たとえば、成功した場合:

    echo json_encode(array("success"    => true,
                           "filename"   => basename($_FILES['image']['name']));
    

    または、成功しなかった場合は、おそらく:

    echo json_encode(array("success"    => false,
                           "error_code" => 42,
                           "error_msg"  => 'File did not upload: '.$e - > getMessage());
    

    明らかに、JSONを返す場合は、PHP)の無関係なecho行を削除する必要がありますが、これがパターンを示していることを願っています。しかし、これにより、次のような応答が生成されます。 AlamofireのresponseJSONで解析できます(またはNSJSONSerializationを使用します)。

  2. または、JSONを予期しないようにAlamofireコードを変更することもできます(たとえば、responseではなくresponseJSONを呼び出す)が、応答の解析ははるかに困難になります。

マイナーで無関係な問題として、私は個人的にそのリクエストを手動で作成するのではなく、Alamofireにそれを任せることをお勧めします。これが READMEの例

Alamofire.upload(
    multipartFormData: { multipartFormData in
        multipartFormData.append(unicornImageURL, withName: "Unicorn")
        multipartFormData.append(rainbowImageURL, withName: "Rainbow")
    },
    to: "https://httpbin.org/post",
    encodingCompletion: { encodingResult in
        switch encodingResult {
        case .success(let upload, _, _):
            upload.responseJSON { response in
                debugPrint(response)
            }
        case .failure(let encodingError):
            print(encodingError)
        }
    }
)

これはSwift 3およびAlamofire4用です。以前のバージョンについては、この質問の改訂履歴を参照してください。

4
Rob

Swift 2 AlamoFire total Solution for image upload to REST API

AlamoFireには、簡素化されたソリューションが多数含まれています。 Alamofire.requestメソッドには、簡単な方法でアップロードするために使用できるいくつかの簡略化されたオーバーロードが含まれています。 Alamofire.request(メソッド開発者は、エンコーディングのオーバーヘッドを取り除くことができます。

以下の私の解決策を確認してください。

ソリューションはSwift 2.0でテストされました

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}
0
Chamath Jeevan
let parameters: Parameters = [
      "userid":user.userID!
    ]

    print("the uploadData - \(parameters)")

    let imageData = UIImageJPEGRepresentation(deviceImage.image!, 1)

    let url = try! URLRequest(url: URL(string:"your URL here")!, method: .post, headers: nil)

    Alamofire.upload(multipartFormData: { (multipartFormData) in
      multipartFormData.append(imageData!, withName: "file_name", fileName: "abc.jpg", mimeType: "image/jpg")
      for (key, value) in parameters {
        multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
      }
    }, with: url, encodingCompletion: { (result) in
            switch result {

            case .success(let upload, _, _):

              upload.responseJSON { response in

                if response.response?.statusCode == 200 {
                  PrepareUIElements.showAlertAndPerformSegue(sender: self, message: "Uploaded Successfully", identifier: "ShowHome")
                } else {
                  print("whatever you want")
                }
              }

            case .failure(let encodingError):
              PrepareUIElements.showAlert(sender: self, message: "Unable to Upload")
              print(encodingError)
            }

    })
0
Ronit