Загрузка файла с параметрами с помощью Alamofire
Я пытаюсь загрузить файл с помощью 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)
}
Невозможно определить, как отправлять дополнительные параметры вместе с загрузкой.
Ответы
Ответ 1
Вот простая функция, которая требует целевого URL-адреса загрузки, параметров и imageData и возвращает URLRequestConvertible и NSData, которые Alamofire.upload требует для загрузки изображения с параметрами.
// 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)
}
Вот пример того, как его использовать (см. CREATE AND SEND REQUEST):
// 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)")
}
И если вам нужен php файл для целевого URL-адреса (с папкой "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);
Ответ 2
Загрузить фото/файл с параметрами и пользовательскими заголовками через 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 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)
}
})
}
Ответ 3
Вот решение, использующее 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)
}
})
Ответ 4
Усиление ответа EdFunke для 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)
}
}
)
Ответ 5
Многостраничная загрузка планируется включить в следующую (1.3.0) версию Alamofire.
Тем временем, используя информацию в этом потоке, я создал класс, который упрощает загрузку файлов и включает в себя дополнительные параметры (обычные "входы" ) в запросе вместе с одним или несколькими файлами.
Не предполагая, что файлы имеют определенный тип или использование маршрутизаторов.
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
Ответ 6
Код в ответе @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)
NetData из https://github.com/nghialv/Net/blob/master/Net/NetData.swift
Код 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 );
?>
Ответ 7
Более короткая версия, основанная на ответах @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)
}
Ответ 8
В то время как есть другие ответы, которые советуют вручную создавать множественные запросы, вы можете просто захотеть придерживаться AFNetworking. Несмотря на то, что он написан в Objective-C, вы все равно можете использовать его в своих проектах Swift (см. Swift и Objective-C в том же проекте). Во всяком случае, код Swift для отправки многостраничного запроса с использованием AFNetworking выглядит следующим образом:
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
или его параметров, но когда вы его компилируете и запускаете, отлично работает.
Ответ 9
Вы получаете 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)")
}
}
}
}
Ответ 10
Ниже приведены быстрые и Php-коды
Быстрый код → 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 данных (Array, Dictionary или String) будет зависеть от запроса в быстрой стороне, здесь См. эту строку в коде
multipartFormData.append(data, withName: "imgFiles []", fileName: "(NSUUID(). UuidString).jpeg", mimeType: "image/jpeg" )
в стороне Php с именем: "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" ], "error": [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);
}
Ответ 11
Я взял ответ на антиблокировку и завернул все это в 1 функцию с обработчиком завершения. Думал, что это может быть полезно для кого-то. Это немного "грубее", а затем ответ на антиблокировку, поскольку я просто беру строковый ответ из файла PHP (а не JSON).
Вот как вы это называете:
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";
}