การอัปโหลดไฟล์ด้วยพารามิเตอร์โดยใช้ Alamofire


95

ฉันพยายามอัปโหลดไฟล์โดยใช้Alamofire. การอัปโหลดทำงานได้ดีเมื่อใช้ File ( 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?

นอกจากนี้ฉันจะส่งข้ามพารามิเตอร์เพิ่มเติมในการอัปโหลดได้อย่างไร

ขอบคุณ

แก้ไข

ฉันไม่ได้ตั้งค่าประเภทเนื้อหาที่ถูกต้อง:

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 และส่งคืน 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)
}    

นี่คือตัวอย่างวิธีการใช้งาน (ดูสร้างและส่งคำขอ):

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

สวัสดีฉันใช้วิธีนี้แล้วและใช้ได้ดี แต่ในฝั่งเซิร์ฟเวอร์พวกเขาเปลี่ยนประเภทเนื้อหาคำขอ JSON หลังจากนั้นวิธีนี้ไม่ได้ผลฉันต้องการอัปโหลดข้อมูลเป็น json ... คุณช่วยฉันได้ไหม
mychar

1
เกือบถูกแล้ว uploadData.appendData ("Content-Disposition: form-data; name = \" file \ "; filename = \" file.png \ "\ r \ n" .dataUsingEncoding (NSUTF8StringEncoding)!) ในชื่อบรรทัดนี้ = \ "file \" ไฟล์คือชื่อคีย์ที่เซิร์ฟเวอร์จะจัดการ.. เหมือนคลิปหนีบกระดาษ
อัลเบิร์ตชิง

Mines ทำงานมาก่อนและตอนนี้ฉันได้รับรหัส NSCocoaErrorDomain 3840 มีใครแก้ปัญหานี้ได้บ้าง
เจ้าพ่อ

@antiblank ขอบคุณสำหรับการแบ่งปันรหัสนี้ คุณช่วยแนะนำวิธีแก้ไขฟังก์ชันนี้เพื่อให้สามารถยอมรับ NSData หรือ null สำหรับพารามิเตอร์รูปภาพได้เนื่องจากผู้ใช้มีตัวเลือกว่าจะอัปโหลดรูปภาพในการเรียกใช้บริการเว็บของฉันหรือไม่ ฉันสามารถใช้ anyObject แทน NSData ในคำจำกัดความได้ไหม
user2363025

3
เราจะทำสิ่งนี้ได้อย่างไรรวมถึงส่วนหัวด้วย
Poonam

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


ส่วนเนื้อหาช่วยบอกฉันเกี่ยวกับบรรทัดด้านล่างนี้ได้ไหมถ้าให้ imageData = UIImageJPEGRepresentation (image, 1) {multipartFormData.append (imageData, withName: "file", fileName: "file.png", mimeType: "image / png")} (คีย์ค่า) ในพารามิเตอร์ {multipartFormData.append ((value? .data (using: .utf8)) !, withName: key)}}
Ravi Ojha

1
นี้จะไม่ทำงานถ้าparametersเป็น[String:Any]เพราะไม่ถูกต้องสำหรับvalue.data(using: .utf8))! Any Typeคุณมีคำแนะนำวิธีแก้ปัญหานี้หรือไม่?
Chlebta

57

นี่คือวิธีแก้ปัญหาโดยใช้ Alamofire 3.0 ตามคำตอบของ antiblanks:

 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 แต่เมื่อฉันทำประเภทนั้นจะอนุมานเป็น () จึงไม่อนุญาตให้เรียกใช้เมธอด ขอบคุณ.
Sean Lintern

@ SeanLintern88: คุณสามารถโทรยกเลิก () ตามคำขอ - วัตถุ สิ่งที่ชอบ: upload.cancel () คุณสามารถกำหนด request-Object ให้กับตัวแปรและโทรยกเลิก ()
EdFunke

1
case .Success(let upload, _, _) uploadไม่สามารถค้นหาได้. ฉันพลาดอะไรไปรึเปล่า?
fatihyildizhan

@fatihyildizhan encodingResultเป็นMultipartFormDataEncodingResultenum .Success Caseมีพารามิเตอร์ต่อไปนี้: ( request: Request, streamingFromDisk: Bool, streamFileURL: NSURL?) ดังนั้นuploadเป็นขอ เพิ่มimport Alamofireรึเปล่า
EdFunke

คุณมีความคืบหน้าอย่างไร?
hris ถึง

10

การปรับปรุงคำตอบของ 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)
                }
            }
        )

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) จะส่งคืนอ็อบเจ็กต์ Request เช่นเดียวกับเมธอด Alamofire.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)

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

?>

คงจะดีไม่น้อยหากคุณระบุสิ่งที่คุณเปลี่ยนแปลงไป มันเป็นการปรับปรุงง่ายๆที่อาจเป็นการแก้ไขคำตอบของ @ 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 เมื่อฉันพยายามใช้รหัสของคุณฉันได้รับข้อผิดพลาดที่เรียกว่า "การใช้ตัวระบุที่ไม่ได้รับการแก้ไข 'เราเตอร์'" ฉันคิดว่าเราเตอร์เป็น enum ที่คุณใช้ที่นี่ คุณช่วยปรับปรุงคำตอบได้ไหม Thankz
Ankahathara

@Ankahathara สร้าง Router enum หรือสร้าง NSURLRequest ด้วยตนเองแทนการใช้ Router github.com/Alamofire/Alamofire
Tom

2

แม้ว่าจะมีคำตอบอื่น ๆ ที่แนะนำวิธีสร้างคำขอหลายส่วนด้วยตนเอง แต่คุณอาจต้องการใช้ 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เมธอดหรือพารามิเตอร์ของมัน แต่เมื่อคุณรวบรวมและเรียกใช้มันก็จะทำงานได้ดี


นี่เป็นจุดที่ดี แต่ฉันคิดว่าชิ้นส่วน "manual" นั้นค่อนข้างเล็กกว่าใน 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 Code เพื่อรับพารามิเตอร์และไฟล์

นี่คือพารามิเตอร์จัดการใน $ _Request

และไฟล์จัดการใน $ _File

รูปแบบในข้อมูล $ _File (Array, Dictionary หรือ String) จะขึ้นอยู่กับการร้องขอในด้านที่รวดเร็วดูบรรทัดนี้ในโค้ด

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

ในฝั่ง Php withName: "imgFiles []" ให้อาร์เรย์ของชื่อรูปแบบประเภท

เช่น

"ชื่อ": ["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], "size": [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 มารวมไว้ในฟังก์ชันเดียวด้วยตัวจัดการที่สมบูรณ์ คิดว่ามันอาจมีประโยชน์สำหรับใครบางคน มันค่อนข้าง 'หยาบกว่า' แล้วคำตอบของ antiblank เพราะฉันแค่ตอบกลับสตริงจากไฟล์ 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";
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.