无法将包含多部分/表单数据的图片上传到服务器 [英] Failing to Upload Picture with multipart/form-data to a Server

查看:121
本文介绍了无法将包含多部分/表单数据的图片上传到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在multipart/form-data上阅读了很多主题.它仍然不起作用.我可以使用URLSession.shared.uploadTask将文件上传到服务器.

I've read quite a lot of topics here on multipart/form-data. It still doesn't work. I am able to upload a file to my server with URLSession.shared.uploadTask.

class MainViewController: UIViewController {
    @IBOutlet weak var pictureView: UIImageView!

    @IBAction func postTapped(_ sender: UIButton) {
        postData()
    }

    func postData() {
        var request = URLRequest(url: URL(string: "http://www.mywebsite.com/upload.php")!)
        request.httpMethod = "POST"
        request.timeoutInterval = 30.0

        guard let imageData = UIImagePNGRepresentation(pictureView.image!) else {
            print("oops")
            return
        }

        let uuid = UUID().uuidString
        let CRLF = "\r\n"
        let filename = uuid + ".png"   // file name
        let formName = uuid + ".png"   // file name in the form
        let type = "image/png"     // file type
        let titleData = "hoge"      // title
        let titleName = uuid + ".png"     // title name in the form
        let boundary = String(format: "----iOSURLSessionBoundary.%08x%08x", arc4random(), arc4random())
        var body = Data()
        // form data //
        body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
        body.append(("Content-Disposition: form-data; name=\"\(titleName)\"" + CRLF + CRLF).data(using: .utf8)!)
        body.append(titleData.data(using: .utf8)!)
        body.append(CRLF.data(using: .utf8)!)
        // file data //
        body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
        body.append(("Content-Disposition: form-data; name=\"\(formName)\"; filename=\"\(filename)\"" + CRLF).data(using: .utf8)!)
        body.append(("Content-Type: \(type)" + CRLF + CRLF).data(using: .utf8)!)
        body.append(imageData)
        body.append(CRLF.data(using: .utf8)!)
        // footer //
        body.append(("--\(boundary)--" + CRLF).data(using: .utf8)!)
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.setValue("\(body.count)", forHTTPHeaderField: "Content-Length")
        request.httpBody = body
        let session = URLSession(configuration: .default)
        session.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print(error)
            }
            if let respose = response {
                print(respose)
            }
        }
        .resume()
    }
}

PHP(索引处为upload.php)

PHP (upload.php at index)

$dir = __DIR__ . '/upload/';
$path = $dir . basename($_FILES['filename']['name']);

$data['result'] = 'failure';
if (move_uploaded_file($_FILES['filename']['tmp_name'], $path)) {
    chmod($path, 0777);
    $data['result'] = date("H:i:s") . ' ' . $_POST['title'] . ' success';
}

header('Content-Type: application/json');
echo json_encode($data);

上面的代码是我尝试过的许多版本之一.没有错响应显示状态码为200.但是服务器中没有文件.我不知道为什么它不起作用?与App Transport Security Settings无关.我还没有准备好使用Alamofire. Muchos Thankos.

The code above is one of many versions I have tried. There's no error. The response says the status code is 200. But there's no file in the server. I wonder why it doesn't work? It's not about App Transport Security Settings. I'm not ready to use Alamofire, yet. Muchos thankos.

推荐答案

我调试了您的代码,进行了简化,为清晰起见,将调试语句保留了下来.这是我想出的:

I debugged your code, simplified and left the debug statements in for clarity. Here is what I came up with:

func postData() {
    var request = URLRequest(url: URL(string: "http://localhost/uploadimages/uploadtry.php")!)
    request.httpMethod = "POST"
    request.timeoutInterval = 30.0

    guard let imageData = UIImagePNGRepresentation(pictureView.image!) else {
        print("oops")
        return
    }

    let CRLF = "\r\n"
    let filename = "user.png"
    let formName = "file"
    let type = "image/png"     // file type

    let boundary = String(format: "----iOSURLSessionBoundary.%08x%08x", arc4random(), arc4random())

    var body = Data()

    // file data //
    body.append(("--\(boundary)" + CRLF).data(using: .utf8)!)
    body.append(("Content-Disposition: form-data; name=\"\(formName)\"; filename=\"\(filename)\"" + CRLF).data(using: .utf8)!)
    body.append(("Content-Type: \(type)" + CRLF + CRLF).data(using: .utf8)!)
    body.append(imageData as Data)
    body.append(CRLF.data(using: .utf8)!)

    // footer //
    body.append(("--\(boundary)--" + CRLF).data(using: .utf8)!)
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    //TW debug the body data.
    let theString:NSString = NSString(data: body as Data, encoding: String.Encoding.ascii.rawValue)!
    print(theString)

    request.setValue("\(body.count)", forHTTPHeaderField: "Content-Length")

    request.httpBody = body
    let session = URLSession(configuration: .default)
    session.dataTask(with: request) { (data, response, error) in
        if let error = error {
            print(error)
        }
        if let respose = response {
            print(respose)
        }
        // TW
        if let data = data {
            // This gives us same as server log

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

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

            // Print out reponse body
            let responseString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
            print("****** response data = \(responseString!)")

        }

        }
        .resume()
}

提到的uploadtry.php

The mentioned uploadtry.php

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);

$dir = 'media';
$path = $dir . "/" . basename($_FILES['file']['name']);


$data['result'] = 'failure';
if (move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
    chmod($path, 0777);
    $data['result'] = ' success';
}

header('Content-Type: application/json');
echo json_encode($data);


?>

基本上,我在服务器上看到了这样的错误:

Basically I saw errors like this on the server:

Undefined index: filename in /pathtoserver/uploadimages/uploadtry.php on line 6

因此服务器无法理解您消息中的文件名. 如果您没有服务器访问权限,则调试语句可帮助您在客户端查看错误.

So the server could not understand filename in your message. The debug statements help you to see the error also on the client side if you have no server access.

希望可以帮助您入门.

这篇关于无法将包含多部分/表单数据的图片上传到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆