将图像数据上传到 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,它可以让您摆脱准备多部分请求的困境。
我有一个 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,它可以让您摆脱准备多部分请求的困境。