Home > other >  Data loss when uploading image data to PHP-Server
Data loss when uploading image data to PHP-Server

Time:01-25

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

  •  Tags:  
  • Related