I have an iOS App which should upload image data to my php server on Nginx with a POST request. I can upload the data but when I download it after, the uploaded file is corrupted and smaller and I can't open it.
I have changed the values for post_max_size, max_input_vars and upload_max_filesize high enough and have all permissions set correctly.
Here is my code:
App:
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";
}
}
?>
Is anything wrong with it?
CodePudding user response:
You’re missing the \r\n\r\n
after Content-Type: image/jpeg
.
E.g.:
body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
And you probably need it after the final boundary, too:
body.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
Also, we generally do not set Content-Length
. Let URLSession
do that for you.
See https://stackoverflow.com/a/26163136/1271826 or consider using a library like Alamofire which gets you out of the weeds of preparing a multipart request.
CodePudding user response:
This article https://stackoverflow.com/a/26163136/1271826 contains a working solution. Thank you @Rob