使用alamofire上传图片

use*_*360 8 upload swift 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)")
    }
Run Code Online (Sandbox Code Playgroud)

这是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)
}
Run Code Online (Sandbox Code Playgroud)

这就是我在控制台中得到的:

REQUEST { URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ } RESPONSE Optional( { URL: http://tranthanhphongcntt.esy.es/task_manager/IOSFileUpload/ } { status code: 200, headers { "Accept-Ranges" = bytes; Connection = close; "Content-Length" = 345; "Content-Type" = "text/html"; Date = "Tue, 25 Aug 2015 10:52:01 GMT"; "Last-Modified" = "Mon, 24 Aug 2015 03:54:55 GMT"; Server = Apache; } }) JSON nil ERROR Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x7f8c68c1c130 {NSDebugDescription=Invalid value around character 0.})

my PHP content:

<? 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());
} ?>
Run Code Online (Sandbox Code Playgroud)

我的代码遵循了这个建议:使用Alamofire上传带参数的文件 .请帮助我,谢谢

Jac*_*ong 6

虽然Rob的答案是正确的,但这是Swift 2.0版本,上传进度更新.

只需复制并粘贴以下代码,更改上传网址,然后添加参数即可.应该像魅力一样工作.

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");
            }
        }
    );
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 4

您的错误告诉您响应不是有效的 JSON。您正在调用responseJSON,表明您正在等待 JSON 响应,但您的服务器代码未生成 JSON。所以有两种解决方案:

  1. 我建议更改 PHP 代码以生成 JSON 响应。

    例如,如果成功:

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

    或者,如果不成功,也许:

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

    echo显然,如果要返回 JSON,则必须删除 PHP 中的无关行,但希望这说明了该模式。但这将生成一个响应,您可以使用 Alamofire 进行解析responseJSON(或使用NSJSONSerialization)。

  2. 或者,您可以将 Alamofire 代码更改为不期望 JSON(例如 callresponse而不是responseJSON),但解析响应会变得更加困难。

作为一个无关紧要的小问题,我个人建议不要手动构建该请求,而是让 Alamofire 为您做这件事。这是自述文件中的示例

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)
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

这是针对 Swift 3 和 Alamofire 4 的。请参阅此问题的先前版本的修订历史记录。