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を使用してパラメータを含むファイルをアップロードする 。助けてください、ありがとう
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");
}
}
);
エラーは、応答が有効なJSONではないことを示しています。 responseJSON
を呼び出しています。これは、JSON応答を期待しているが、サーバーコードがJSONを生成していないことを示しています。したがって、2つの解決策があります。
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
を使用します)。
または、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用です。以前のバージョンについては、この質問の改訂履歴を参照してください。
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.
}
}
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)
}
})