0
votes

I am trying to do a simple POST request to a 3rd party API. The API accepts a file as a BODY parameter. Specifically, the file content must be binary:

enter image description here

I have successfully posted to this 3rd party API using Postman, with below body configuration:

enter image description here

When uploading the file, I am using Laravel. This is the code:

//$document is a class of "UploadedFile"
$tempfile = Storage::disk('local')->putFile('/temp', $document);

I am then simply trying to post this file using Guzzle:

use Illuminate\Support\Facades\Http;

$filepath = storage_path('app/' . $tempfile);
$post = Http::attach('file', file_get_contents($tempfile), 'myfile.pdf')->post('example.org')->json());

However, the 3rd party API does not recognize this as a PDF file:

Content type must be one of application/vnd.hypatos.ocr+json application/pdf image/tiff image/jpeg image/png text/xml application/xml

What am I doing wrong compared to the request I am sending in Postman? It is the exact same file I am trying to post to the API.

2

2 Answers

2
votes

Have you tried to specify your Content-Type in your request headers like so

Http::attach('file', file_get_contents($tempfile), 'myfile.pdf')->withHeaders([
    'Content-Type' => 'application/pdf',
])->post('example.org')->json();
1
votes

try copying the code directly from postman see what you might be missing.

so this is a good question because working with binary data can be tricky. I haven't done exactly what you are attempting to do but, I have made a laravel page that uploads a spreadsheet processes that changes data then pops up a download of the modified spreadsheet. and working with binary was a complete pain but here is what I learned. First the basic form.

<input id="file" type="file" class="form-control" name="file" style="height:auto;" required />

then the ajax for upload

$.ajax({
            async: true,
            method: 'POST',
            enctype: 'multipart/form-data',
            processData: false,
            contentType: false,
            cache: false,
            url: "priceIncrease/parseHeaders",
            data: formData,
            xhr: function () {
                var myXhr = $.ajaxSettings.xhr();
                if (myXhr.upload) {
                    myXhr.upload.addEventListener('progress', progress, false);
                }
                return myXhr;
            }
        });

There is extra in here thats handling progress bars but it isnt related to working with binary data so I will just skip it.

Now I parse the file into an array process it and want to return a spreadsheet to the user this is where the binary gigery pokery starts. When I return the data I had to encode it as base64

$fqn = storage_path() . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . $priceIncreaseResult['filepath'] . $priceIncreaseResult['filename'];
$response = base64_encode(file_get_contents($fqn));

Then on the frontend I gave it the mime type and converted back out of base64

if(data['progress']['file']){
                var result = data['progress']['file'];
                var a = document.createElement("a");
                var file = document.getElementById("file");
                var filename = file.files[0].name;
                console.log(filename);
                var blob = new Blob([s2ab(atob(result))], {
                    type: 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'
                });
                a.href = URL.createObjectURL(blob);
                a.download = filename;
                document.body.appendChild(a);
                a.click();
                a.remove();
            }

the final piece here is the type conversion

        function s2ab(s) {
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
        return buf;
    }

I know this isnt a one off answer but, I do hope you get some incite about working with binary data.