如何使用 Swift 将图像上传到 iOS 中的服务器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26335656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:09:20  来源:igfitidea点击:

How to upload images to a server in iOS with Swift?

iosswift

提问by trees in Taiwan

It won't work, how to send an image from an iOS Swift app to my PHP server?

它不起作用,如何将图像从 iOS Swift 应用程序发送到我的 PHP 服务器?

@IBAction func upload(sender: UIButton) {

    var imageData = UIImageJPEGRepresentation(img.image, 90)
   // println(imageData)
    let url = NSURL(string:"http://www.i35.club.tw/old_tree/test/uplo.php")
    //let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
    //var request = NSMutableURLRequest(URL: url, cachePolicy: cachePolicy, timeoutInterval: 10)
    var request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"

    // set Content-Type in HTTP header
    let boundaryConstant = "----------V2ymHFg03esomerandomstuffhbqgZCaKO6jy";
    let contentType = "multipart/form-data; boundary=" + boundaryConstant
    NSURLProtocol.setProperty(contentType, forKey: "Content-Type", inRequest: request)
    request.HTTPBody = imageData
    // set data
    //var dataString = "adkjlkajfdadf"
    //let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
    //request.HTTPBody = requestBodyData


    //

    request.addValue(contentType, forHTTPHeaderField: "Content-Type")
    request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
    //
    // set content length

    //NSURLProtocol.setProperty(requestBodyData.length, forKey: "Content-Length", inRequest: request)

    var response: NSURLResponse? = nil
    var error: NSError? = nil
    let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)

    let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
    println("API Response: \(results)")
}

//take photo
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {


    var selectedImage : UIImage = image
     img.image = selectedImage
    UIImageWriteToSavedPhotosAlbum(selectedImage, nil, nil, nil)
    self.dismissViewControllerAnimated(true, completion: nil)

}

回答by Vinod Joshi

I have taken the photo by user's choice and written code for swift 2 and iOS9

我已经根据用户的选择拍摄了照片,并为 swift 2 和 iOS9 编写了代码

    func imageUploadRequest(imageView imageView: UIImageView, uploadUrl: NSURL, param: [String:String]?) {

        //let myUrl = NSURL(string: "http://192.168.1.103/upload.photo/index.php");

        let request = NSMutableURLRequest(URL:uploadUrl);
        request.HTTPMethod = "POST"

        let boundary = generateBoundaryString()

        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

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

        if(imageData==nil)  { return; }

        request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)

        //myActivityIndicator.startAnimating();

        let task =  NSURLSession.sharedSession().dataTaskWithRequest(request,
            completionHandler: {
                (data, response, error) -> Void in
                if let data = data {

                    // You can print out response object
                    print("******* response = \(response)")

                    print(data.length)
                    // you can use data here

                    // Print out reponse body
                    let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
                    print("****** response data = \(responseString!)")

                    let json =  try!NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? NSDictionary

                    print("json value \(json)")

                    //var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err)

                    dispatch_async(dispatch_get_main_queue(),{
                        //self.myActivityIndicator.stopAnimating()
                        //self.imageView.image = nil;
                    });

                } else if let error = error {
                    print(error.description)
                }
        })
        task.resume()


    }


    func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
        let body = NSMutableData();

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }

        let filename = "user-profile.jpg"

        let mimetype = "image/jpg"

        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.appendData(imageDataKey)
        body.appendString("\r\n")

        body.appendString("--\(boundary)--\r\n")

        return body
    }

    func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().UUIDString)"
    }

}// extension for impage uploading

extension NSMutableData {

    func appendString(string: String) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
        appendData(data!)
    }
}


--------- following code for the php side

--------- php端如下代码

<?php

$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$userId = $_POST["userId"];

$target_dir = "media";

if(!file_exists($target_dir))
{
mkdir($target_dir, 0777, true);
}

$target_dir = $target_dir . "/" . basename($_FILES["file"]["name"]);

if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir)) 
{
echo json_encode([
"Message" => "The file ". basename( $_FILES["file"]["name"]). " has been uploaded.",
"Status" => "OK",
"userId" => $_REQUEST["userId"]
]);

} else {

echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_REQUEST["userId"]
]);

}

回答by Annu

To upload image with parameters use this code,

要上传带有参数的图像,请使用此代码,

 // Your method to upload image with parameters to server.     

func uploadImageOne(){
    var imageData = UIImagePNGRepresentation(imageView.image)

    if imageData != nil{
        var request = NSMutableURLRequest(URL: NSURL(string:"Enter Your URL")!)
        var session = NSURLSession.sharedSession()

        request.HTTPMethod = "POST"

        var boundary = NSString(format: "---------------------------14737809831466499882746641449")
        var contentType = NSString(format: "multipart/form-data; boundary=%@",boundary)
      //  println("Content Type \(contentType)")
        request.addValue(contentType, forHTTPHeaderField: "Content-Type")

        var body = NSMutableData.alloc()

        // Title
         body.appendData(NSString(format: "\r\n--%@\r\n",boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format:"Content-Disposition: form-data; name=\"title\"\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData("Hello World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)

        // Image
        body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"img.jpg\"\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(imageData)
        body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)



        request.HTTPBody = body


        var returnData = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)

        var returnString = NSString(data: returnData!, encoding: NSUTF8StringEncoding)

        println("returnString \(returnString)")

    }


}

回答by Den

My updated code for Swift 3

我更新的Swift 3代码

func uploadImage() {
    let url = URL(string: "YOUR SERVER URL");
    let request = NSMutableURLRequest(url: url!);
    request.httpMethod = "POST"
    let boundary = "Boundary-\(NSUUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    var retreivedImage: UIImage? = nil
    //Get image
    do {
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let readData = try Data(contentsOf: URL(string: "file://\(documentsPath)/myImage")!)
        retreivedImage = UIImage(data: readData)
        addProfilePicView.setImage(retreivedImage, for: .normal)
    }
    catch {
        print("Error while opening image")
        return
    }

    let imageData = UIImageJPEGRepresentation(retreivedImage!, 1)
    if (imageData == nil) {
        print("UIImageJPEGRepresentation return nil")
        return
    }

    let body = NSMutableData()
    body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
    body.append(NSString(format: "Content-Disposition: form-data; name=\"api_token\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
    body.append(NSString(format: (UserDefaults.standard.string(forKey: "api_token")! as NSString)).data(using: String.Encoding.utf8.rawValue)!)
    body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
    body.append(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"testfromios.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
    body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
    body.append(imageData!)
    body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)

    request.httpBody = body as Data

    let task =  URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
        (data, response, error) -> Void in
        if let data = data {
           // do what you want in success case   
        } else if let error = error {
            print(error.localizedDescription)
        }
    })

    task.resume()
}

And PHP side code you can take from @VinodJoshianswer.

您可以从@VinodJoshi答案中获取 PHP 侧代码。

回答by Silversky Technology

I have made function for Block method which is easy to use and this is class function so you can use anywhere in your project for example make

我为 Block 方法制作了函数,它易于使用,这是类函数,因此您可以在项目中的任何地方使用,例如 make

MVCServer.swift  

NSObject class and

NSObject 类和

import Alamofire 

and then write this function in this class

然后在这个类中写这个函数

 func postImageRequestWithURL(withUrl strURL: String,withParam postParam: Dictionary<String, Any>,withImages imageArray:NSMutableArray,completion:@escaping (_ isSuccess: Bool, _ response:NSDictionary) -> Void)
{

    Alamofire.upload(multipartFormData: { (MultipartFormData) in

        // Here is your Image Array
        for (imageDic) in imageArray
        {
            let imageDic = imageDic as! NSDictionary

            for (key,valus) in imageDic
            {
                MultipartFormData.append(valus as! Data, withName:key as! String,fileName: "file.jpg", mimeType: "image/jpg")
            }
        }

        // Here is your Post paramaters
        for (key, value) in postParam
        {
            MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
        }

    }, usingThreshold: UInt64.init(), to: strURL, method: .post) { (result) in

        switch result {
        case .success(let upload, _, _):

            upload.uploadProgress(closure: { (progress) in
                print("Upload Progress: \(progress.fractionCompleted)")
            })

            upload.responseJSON { response in

                if response.response?.statusCode == 200
                {
                    let json = response.result.value as? NSDictionary

                    completion(true,json!);
                }
                else
                {
                    completion(false,[:]);
                }
            }

        case .failure(let encodingError):
            print(encodingError)

            completion(false,[:]);
        }

    }
}

Now Call this Function

现在调用这个函数

var ImageArray : NSMutableArray!

// Here is your post parameter 
var parameters: [String:Any] = ["user_master_id" : “56”,
                                        "first_name": “Jignesh”,
                                        "last_name" : “Mayani”,
                                        "email": “[email protected]”]
// Here is your image is in DATA formate don't send as UIImage formate       
let ImageDic = ["profile_image" : imageData!]

// Here you can pass multiple image in array i am passing just one 
ImageArray = NSMutableArray(array: [ImageDic as NSDictionary])

MVCServer().postImageRequestWithURL(withUrl: "write Your URL here", withParam: parameters, withImages: ImageArray) { (isSuccess, response) in
      // Your Will Get Response here   
    }

回答by Vincent van Leeuwen

I would recommend to take a look at: https://github.com/sraj/Swift-SRWebClient

我建议看看:https: //github.com/sraj/Swift-SRWebClient

Sample function that worked for me:

对我有用的示例函数:

func uploadImage(image:UIImage) {
  let imageData:NSData = UIImageJPEGRepresentation(image, 100)
  SRWebClient.POST("http://www.example.com/upload/")
    .data(imageData, fieldName:"photo", data: ["foo":"bar","baz":"qux"])
    .send({(response:AnyObject!, status:Int) -> Void in
        // process success response
    },failure:{(error:NSError!) -> Void in
        // process failure response
    })
}

You'll notice that the above code is a slightly adjusted version of the snippets on the Swift-SRWebClient Github page. I've replaced NSData.dataWithDatawith UIImageJPEGRepresentationas the former is deprecated.

您会注意到,上面的代码是对 Swift-SRWebClient Github 页面上的代码段稍加调整的版本。我已经替换了NSData.dataWithDataUIImageJPEGRepresentation因为前者已被弃用。

Also, don't forget to drag SRWebClient.swiftinto your project folder, otherwise this won't work :)

另外,不要忘记拖入SRWebClient.swift您的项目文件夹,否则这将不起作用:)

回答by Sport

try like this

像这样尝试

@IBAction func upload(sender: UIButton) {

    var imageData = UIImageJPEGRepresentation(img.image, 90)
    var url = NSURL(string: "http://www.i35.club.tw/old_tree/test/uplo.php")
            var request = NSMutableURLRequest(URL: url)
            request.HTTPMethod = "POST"
            request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(imageData))

            var response: NSURLResponse? = nil
    var error: NSError? = nil
    let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)

    let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
    println("API Response: \(results)")
    }       

refer this link

参考这个链接

回答by Duncan

This is great, I've been trying to pass an image using REST for a while and coouldn't format it just right and kept getting timeout errors. Using createBodyWithParameters I was able to make it work.

这太棒了,我一直在尝试使用 REST 传递图像一段时间,但无法正确格式化并不断收到超时错误。使用 createBodyWithParameters 我能够让它工作。

Here's the Swift 3 version of the code:

这是代码的 Swift 3 版本:

func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: UIImage, boundary: String) -> Data {
  var body = Data();

  if parameters != nil {
     for (key, value) in parameters! {
        body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
        body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
        body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
     }
  }

  let filename = "user-profile.jpg"

  let mimetype = "image/jpg"

  body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
  body.append("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n".data(using: String.Encoding.utf8)!)
  body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
  body.append(UIImageJPEGRepresentation(imageDataKey, 1)!)
  //body.appendData(imageDataKey)
  body.append("\r\n".data(using: String.Encoding.utf8)!)

  body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)

  return body
}

回答by Roman Romanenko

Just look on that simple explanation:

看看那个简单的解释:

Form data and multipart uploads with URLRequest

使用 URLRequest 表单数据和分段上传

Also, to keep code up to date you can replace NSMutableDataon Data. So your final code will be looks like:

此外,为了使代码保持最新,您可以NSMutableDataData. 所以你的最终代码看起来像:

func createHttpBody(parameters: [String: String]? = nil, _ boundary: String, data: Data, mimeType: String, filename: String) -> Data {
    var body = Data()

    let boundaryPrefix = "--\(boundary)\r\n"

    if let parameters = parameters {

        for (key, value) in parameters {
            body.append(boundaryPrefix)
            body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
            body.append("\(value)\r\n")
        }
    }

    body.append(boundaryPrefix)
    body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n")
    body.append("Content-Type: \(mimeType)\r\n\r\n")
    body.append(data)
    body.append("\r\n")
    body.append("--".appending(boundary.appending("--")))

    return body
}

And updated extension for Datato use appendmethod:

并更新Data了使用append方法的扩展名:

extension Data {

    mutating func append(_ string: String) {

        if let data = string.data(using: .utf8) {
            append(data)
        }
    }
}

Also you can check this video tutorialand check source codefor that tutorial.

您也可以查看此视频教程并查看该教程的源代码

回答by Gowtham Sooryaraj

func imageUpload(imageData:String){       
 var request:NSMutableURLRequest!
        let param:String = ""
        request = NSMutableURLRequest(url: URL(string: "www.pickmyoffers.com")!)// use your upload php file link and parameter "example.com/upload.php?image=\(imageData)"

        request.httpMethod = "POST"

        request.httpBody = param.data(using: String.Encoding.utf8)
        let session = URLSession.shared
        let task = session.dataTask(with: request as URLRequest) {data,response,error in
            if error != nil {
                print("error=\(error)")
                return
            }
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print(responseString!)
        }
        task.resume()
}

回答by iOS

In swift 4.1 and Xcode 9.4.1

在 swift 4.1 和 Xcode 9.4.1 中

See my Code in this blog for Upload image to server in Swift

请参阅此博客中的代码,以在 Swift 中将图像上传到服务器

https://markingios.blogspot.com/2018/09/upload-image-to-server-in-swift.html

https://markingios.blogspot.com/2018/09/upload-image-to-server-in-swift.html

Call this function like : uploadImage()

像这样调用这个函数:uploadImage()

func uploadImage(){

let imageData = UIImageJPEGRepresentation(yourImage!, 1.0)//Replace your image

if imageData != nil{
   var request = URLRequest(url: NSURL(string:urlString)! as URL)//Send your URL here
   print(request)

   request.httpMethod = "POST"

   let boundary = NSString(format: "---------------------------14737809831466499882746641449")
   let contentType = NSString(format: "multipart/form-data; boundary=%@",boundary)
   //  println("Content Type \(contentType)")
   request.addValue(contentType as String, forHTTPHeaderField: "Content-Type")

   var body = Data()

   body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
   body.append(NSString(format:"Content-Disposition: form-data;name=\"title\"\r\n\r\n").data
                        (using:String.Encoding.utf8.rawValue)!)
   body.append("Hello".data(using: String.Encoding.utf8, allowLossyConversion: true)!)


   body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
   body.append(NSString(format:"Content-Disposition: form-data;name=\"uploaded_file\";filename=\"image.jpg\"\r\n").data
                       (using:String.Encoding.utf8.rawValue)!) //Here replace your image name and file name
   body.append(NSString(format: "Content-Type: image/jpeg\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
   body.append(imageData!)
   body.append(NSString(format: "\r\n--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)

   request.httpBody = body

   let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil      
       else { // check for fundamental networking error
       print("error=\(String(describing: error))")
       SharedClass.sharedInstance.alert(view: self, message: "\(String(describing: error!.localizedDescription))")
       return
    }

    if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 500 {
        SharedClass.sharedInstance.alert(view: self, message: "Server Error")
    } else if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
         print("statusCode should be 200, but is \(httpStatus.statusCode)")
         print("response = \(String(describing: response))")
    }

    //This can print your response in string formate        
    let responseString = String(data: data, encoding: .utf8)
     //            let dictionary = data
     //            print("dictionary = \(dictionary)")
     print("responseString = \(String(describing: responseString!))")

     do {
         self.response3 = (try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject])!
         print(self.response3)

         if (((self.response3["Response"] as? [String : Any])?["status"]) as! String == "SUCCESS") {
               let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
                   SharedClass.sharedInstance.alert(view:self, message: message)
          } else {
                let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
                    SharedClass.sharedInstance.alert(view:self, message: message)
                }

      } catch let error as NSError {
           print(error)
           print(error.localizedDescription)
      }
   }

    task.resume()

 }


}