将图像数据上传到 PHP-服务器时数据丢失

Data loss when uploading image data to PHP-Server

我有一个 iOS 应用程序,它应该使用 POST 请求将图像数据上传到我在 Nginx 上的 php 服务器。我可以上传数据,但是我下载后,上传的文件损坏了,而且变小了,我打不开。

我已将 post_max_size、max_input_vars 和 upload_max_filesize 的值更改得足够高,并且正确设置了所有权限。

这是我的代码:

应用程序:

DispatchQueue.global().async {
    let url = "url to upload.php"
    
    var urlComponents = URLComponents(string: url!)
    urlComponents.queryItems = [
        URLQueryItem(name: "filetype", value: "img")
    ]

    var request = URLRequest(url: urlComponents.url!)
    request.httpMethod = "POST"

    let boundary = UUID().uuidString
    let contentType = "multipart/form-data; boundary=\(boundary)"

    var body = Data()

    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"username\"\r\n\r\n".data(using: .utf8)!)
    body.append("\(username)\r\n".data(using: .utf8)!)
            
    body.append("--\(boundary)\r\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\"image-upload\"; filename=\"img.jpg\"".data(using: .utf8)!)
    body.append("Content-Type: image/jpeg".data(using: .utf8)!)
    body.append(imageData) // 2735963 bytes

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

    request.setValue(contentType, forHTTPHeaderField: "Content-Type")

    request.httpBody = body

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
                
            if error != nil {
                print(error!.localizedDescription)
                return
            }
                
                
            let responseString = String(data: data!, encoding: .utf8)
            print(responseString!) // final data stored on server: 2734537 bytes

                
    }
    task.resume()
}

PHP:

<?php

$user = $_POST['username'];///I need this for the path
$username = str_replace(array("\r", "\n", "'"), '', $user);
$type = $_GET['filetype'];

if ($type == "img")
{
    $path = "path to save img.jpg";
    $image = $_FILES['image-upload']['tmp_name'];

    if (move_uploaded_file($image, $path)) {
        echo "Success";
    }
    else
    {
        echo "Failed";
    }
}

?>

有什么问题吗?

您在 Content-Type: image/jpeg 之后缺少 \r\n\r\n

例如:

body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)

在最终边界之后您可能也需要它:

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

另外,我们一般不设置Content-Length。让 URLSession 为您完成。

请参阅 or consider using a library like Alamofire,它可以让您摆脱准备多部分请求的困境。