1

This issue I'm having could be literally anything in my workflow, but I will start with this scope for now...

I have a rest api that you send a JSON structure and it sends back an excel file, but I can't get it to work probably in the browser/Javascript.

My Javascript code in the browser is basically the following:

    fetch('myapiurl')
    .then(response => response.blob)
    .then(blob => downloadBlob(blob))

    function downloadBlob(blob){
        const a = document.createElement("a");
        a.href = URL.createObjectURL(blob);
        a.download = 'export.xlsx;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }

But this generates a corrupted file, there's either something missing or I'm not sending the file in the right encoding.

Here's the python code from the API in the part where it sends the file (it's an AWS lambda):

output = BytesIO()
#Code that puts an excel file in output
return {
        'statusCode' : 200,
        'headers' : {
            'Content-Disposition': 'attachment; filename="export.xlsx"',
            'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Access-Control-Allow-Origin': '*'
        },
        #I can't return raw bytes so I transform it into a string
        'body' : output.getvalue().hex(),
    }

Am I sending the file the wrong way?

I tried sending it as base64 but it still was corrupted

It works if I make a test locally using python and just bytes.fromhex() the api response and write it in a file in byte mode.

I wonder if AWS Api Gateway is automatically encoding my body as base64

1 Answer 1

1

Make this change and it might work
- .then(response => response.blob)
+ .then(response => response.blob())


Regarding the response body

    #I can't return raw bytes so I transform it into a string
    'body' : output.getvalue().hex(),

you can't send back a hex string, you need to send the raw data. otherwise you would have to convert the hex back to binary as well on the client side before making a blob and later a objectURL


As you may already know the browser will not save an attachment if you fetch it with ajax, what you have to do is "navigate" to the file to trigger the download. And since you are posting json data and converting it to excel you have to do a form submit to send the data over to the server instead of using ajax, since it's not a regular GET request?

<form hidden method="post" enctype="text/plain" action="url">
  <textarea name="json">{"a":12}</textarea>
  <input type="submit">
</form>

This would be better as you don't have to hold all data in the browsers memory before the file can be saved, besides, you can start saving the file much earlier

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.