【问题标题】:Swift PHP file upload with parameters带参数的 Swift PHP 文件上传
【发布时间】:2017-07-24 23:48:05
【问题描述】:

我一直在开发一个应用程序,您可以在其中拍照,然后通过 PHP (POST) 将其发送到服务器。一切正常,我明白了。但现在我在想,如果你能显示拍摄照片的用户的名字会更好。问题是,我不知道如何将参数从这个函数发送到 PHP $_POST。我尝试使用 request.httpBody 但是当我运行 PHP 文件时它说变量中没有值。我的代码如下所示:

func subirFotoRequest(){
let url = URL(string: "http://192.168.0.155/BolsaTrabajo/imagen.php")

let request = NSMutableURLRequest(url: url!)
request.httpMethod = "POST"

let postString = "username\(userName)&userlastname\(lastName)"
//Where userName and lastName are global variables declared before//

let request.httpBody = postString.data(using: String.Encoding.utf8)

let boundary = generateBoundaryString()

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

if (imageView.image == nil)
{
    return
}

let image_data = UIImagePNGRepresentation(imageView.image!)

if(image_data == nil)
{
    return
}

let body = NSMutableData()
indicadorActividad.startAnimating()

let fname = "test.png"
let mimetype = "image/png"


body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"test\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("hi\r\n".data(using: String.Encoding.utf8)!)

body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fname)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(image_data!)
body.append("\r\n".data(using: String.Encoding.utf8)!)

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

request.httpBody = body as Data
let session = URLSession.shared

let task = URLSession.shared.dataTask(with: request as URLRequest) {            (
    data, response, error) in

    guard let _:Data = data, let _:URLResponse = response  , error == nil else {
        print("error")
        return
    }

    let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)

    print(dataString)
    //self.indicadorActividad.stopAnimating()



    do {
    DispatchQueue.main.async(execute: {
        self.indicadorActividad.stopAnimating()

        self.imageView.image = nil;
        });
    }
    catch{
        //Errores
    }


   }
   task.resume()       
  }    

func generateBoundaryString() -> String
{
    return "Boundary-\(UUID().uuidString)"
}

【问题讨论】:

    标签: php ios swift parameter-passing


    【解决方案1】:

    更新

    用户ID示例:

    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition:form-data; name=\"userID\"\r\n\r\n".data(using: String.Encoding.utf8)!)
    body.append("{value of userID}\r\n".data(using: String.Encoding.utf8)!)
    

    起源

    您的代码使用form-data 发布价值。

    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition:form-data; name=\"test\"\r\n\r\n".data(using: String.Encoding.utf8)!)
    body.append("hi\r\n".data(using: String.Encoding.utf8)!)
    

    以上代码为键test 生成后值hi。 只需输入您的用户名...就像这样。

    【讨论】:

    • 嗨 Codus,首先感谢您抽出宝贵的时间来回答。你能再解释一下吗?(Hi 作为测试的关键)例如,如果我想添加另一个参数,我是否应该添加另一行如“Hi”,然后将其替换为,比如说,userID?跨度>
    • 如你所见,--\(boundary)\r\nContent-Disposition:form-data; name=\"test\"\r\n\r\nhi\r\n 把参数放得一干二净。我可以得到$_POST["test"] 的值(hi)。
    • 哦,我明白了,所以如果我想调用 $_Post['ID'] 代码看起来像... --(boundary)\r\nContent-Disposition:form-data; name=\"Id\"\r\n\r\nId\r\n 正确吗?
    • 感谢代码更新,我现在开始看清楚了
    • 是的,注意大小写区别IDId :)
    【解决方案2】:

    NSMutableURLRequest(或URLRequest)不能有多个httpBodys。 (而且 HTTP 协议不能在一个请求中发送多个正文。)

    所以,删除这些行:

        let postString = "username\(userName)&userlastname\(lastName)"
        //Where userName and lastName are global variables declared before//
    
        let request.httpBody = postString.data(using: String.Encoding.utf8)
    

    (后一行肯定会导致编译时错误,但这是另一回事。)

    并稍后替换分配httpBody 的行:

        //### Use `Data` rather than `NSMutableData` in Swift.
        var body = Data()
        indicadorActividad.startAnimating()
    
        let fname = "test.png"
        let mimetype = "image/png"
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"username\"\r\n\r\n".data(using: .utf8)!)
        //### Assuming `userName` and `lastName` are non-Optional.
        body.append("\(userName)\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"userlastname\"\r\n\r\n".data(using: .utf8)!)
        body.append("\(lastName)\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fname)\"\r\n".data(using: .utf8)!)
        body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: .utf8)!)
        body.append(image_data)
        body.append("\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
        //### No need to cast, when you use `Data`.
        request.httpBody = body
    

    当您想发送除图像之外的文本参数时,您可以在 multipart 中添加其他 part,例如在代码中添加 "test"。 (哦,它已经在 Codus 的回答中显示了。)


    这不是使您的代码工作的强制性要求,但您的代码更 Swift-ish 将是:

    func subirFotoRequest() {
        //### If you eventually need forced-upwrapping, do it as soon as possible!
        let url = URL(string: "http://192.168.0.155/BolsaTrabajo/imagen.php")!
    
        //### Use `URLRequest` rather than `NSMutableURLRequest` in Swift.
        //### Please do not miss, it's `var` not `let`.
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
    
        let boundary = generateBoundaryString()
    
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
        //### Consider using `guard` for early-return pattern.
        guard let image = imageView.image else {
            //### Silently ignoring unusual case may not be good for debugging.
            print("imageView.image == nil")
            return
        }
    
        //### (same as above)
        guard let image_data = UIImagePNGRepresentation(image) else {
            print("UIImagePNGRepresentation returned nil")
            return
        }
    
        //### Use `Data` rather than `NSMutableData` in Swift.
        var body = Data()
        indicadorActividad.startAnimating()
    
        let fname = "test.png"
        let mimetype = "image/png"
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"username\"\r\n\r\n".data(using: .utf8)!)
        //### Assuming `userName` and `lastName` are non-Optional.
        body.append("\(userName)\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"userlastname\"\r\n\r\n".data(using: .utf8)!)
        body.append("\(lastName)\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fname)\"\r\n".data(using: .utf8)!)
        body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: .utf8)!)
        body.append(image_data)
        body.append("\r\n".data(using: .utf8)!)
    
        body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
        //### No need to cast, when you use `Data`.
        request.httpBody = body
    
        //### No need to cast, when you use `URLRequest`.
        let task = URLSession.shared.dataTask(with: request) {
            (data, response, error) in
    
            guard let data = data, response != nil, error == nil else {
                print("error")
                return
            }
    
            //### Use `String` rather than `NSString` in Swift.
            let dataString = String(data: data, encoding: .utf8)
    
            //### Supplying default value prevents output "Optional(...)".
            print(dataString ?? "Undecodable result")
    
            //### No code throws here.
            DispatchQueue.main.async {
                self.indicadorActividad.stopAnimating()
    
                self.imageView.image = nil
            }
        }
        task.resume()
    }
    

    【讨论】:

    • 感谢您让我的代码更加“Swifty”,我会像您和 Codus 所说的那样对其进行编辑、进行一些更改并在“多部分”区域添加更多内容
    猜你喜欢
    • 1970-01-01
    • 2019-07-21
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2014-11-27
    • 2014-11-25
    相关资源
    最近更新 更多