2

I'm trying to upload a file from a '<form enctype="multipart/form-data"><input type="file">...' to AWS via a presigned URL using PHP Curl.

While the file appears to be uploaded successfully, after I download the recently uploaded file, trying to open the newly downloaded file fails. I get either "this file is corrupted" or "it looks like we don't support this file format" or "we cant open this file" depending on the file type. I'm getting no response from AWS via curl_exec or curl_error on the upload.

I basically copied the PHP code from POSTMAN since POSTMAN uploads the file successfully when the file is attached as "binary". Since my code attaches the file via CURLOPT_POSTFIELDS in my code, could this be a problem? Every other example I've seen attaches the file via curl_file_create and CURLOPT_POSTFIELDS, so that's what I'm using.

The only instructions I have in uploading the file is:

curl -X PUT \
  "https://PRESIGNED_PUT_URL_FROM_RESPONSE" \
  --upload-file ~/Documents/Files/the_file.pdf

I've tried to change the content-type in the header to the actual uploaded file type, but neither works. I've tried both CURLFile and curl_file_create. The files after uploading to my test server and my website server are all still valid prior to upload to AWS.

    $file_name = $post_files[$FILES_file]["name"];
    $content_type = $post_files[$FILES_file]["type"];
    $TheFileSize = $post_files[$FILES_file]["size"];
    $tmp_name = $post_files[$FILES_file]["tmp_name"];
    $curl = curl_init();
    $cFile = curl_file_create($tmp_name, $content_type, $file_name);

    $payload = array('upload-file' => $cFile);

    $curlOptions = array(
            CURLOPT_URL            => $TheAWSPresignedURL,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_CUSTOMREQUEST  => "PUT",
            CURLOPT_ENCODING       => "",
            CURLOPT_POST           => 1,
            CURLOPT_MAXREDIRS      => 10,
            CURLOPT_TIMEOUT        => 300,
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
            CURLOPT_INFILESIZE     => $TheFileSize,
            CURLOPT_HTTPHEADER     => array(
                "Accept: */*",
                "Accept-Encoding: gzip, deflate",
                "Cache-Control: no-cache",
                "Connection: keep-alive",
                "Content-Length: ".$TheFileSize,
                "Content-Type: multipart/form-data",
                "Host: s3.amazonaws.com"
            ),
        );
    curl_setopt_array($curl, $curlOptions);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);  
    $response = curl_exec($curl);

I'm looking for the file to be uploaded successfully to AWS via a presigned URL, downloaded successfully, and opened successfully.

[UPDATE]

Attempted to upload text files instead of images and pdfs, which were the main file types we were developing for. Downloading those files ended up being "successful" in that I was able to open them up, however, there was text added to the beginning of the text file.

If uploaded as Content-Type:multipart/form-data, the file was still downloadable, but when opened it, this text was added to the beginning of the file.

--------------------------9cd644e15677104b Content-Disposition: form-data; name="upload-file"; filename="SimpleTextFile.txt" Content-Type: text/plain

If uploaded as Content-Type: $content_type, the download link opened the file in a new browser window with this text added to the file.

--------------------------3dca3db029b41ae2 Content-Disposition: attachment; name="upload-file"; filename="SimpleTextFile2.txt" Content-Type: text/plain

lysv
  • 31
  • 5
  • I would start by comparing the downloaded file with the one which you uploaded. You can create a [md5 hash](https://www.lifewire.com/validate-md5-checksum-file-4037391) for both files and if it differs, that would indicate the file contents got changed somewhere! Also open the downloaded file in a text editor and compare the contents. Many times I've seen that the server may included header items which could be seen as corruption. – xk0der Oct 30 '19 at 22:44
  • I dont think you should be providing "Content-Type: multipart/form-data" for a file? Have you tried "Content-Type: application/pdf" for a PDF? There are also libraries for getting the correct MIME type of the document to pass to the header. You can also add 3x verbosity to the curl command and copy the output from there: `curl -vvv -X PUT \ "https://PRESIGNED_PUT_URL_FROM_RESPONSE" \ --upload-file ~/Documents/Files/the_file.pdf` – Simon Oct 30 '19 at 23:04
  • If I change the Content-Type line to: `"Content-Type: ".$content_type,` it still fails after a seemingly successful upload. Instead of downloading a file that is corrupted though, the download link opens in a new window that tries to serve the file. – lysv Nov 01 '19 at 16:59

1 Answers1

1

Replacing $payload = array('upload-file' => $cFile); with $payload = file_get_contents( $tmp_name ); solved my issue. Looks like I don't need curl_file_create or the array and key upload-file at all.

Also, https://stackoverflow.com/a/21888136 metioned loading the content directly should remove the header information, and it did.

Thanks all for insight, as you did point me in the right direction!

lysv
  • 31
  • 5