Binary file routing - headers settings

I’ve been struggling with this for a while now.

I have a smart action which purpose is to download a pre-filled odt file:

{
    name: 'Générer un courrier',
    type: 'single',
    download: true,
}

In my route, it look like this :

router.post('/actions/generer-un-courrier', permissionMiddlewareCreator.smartAction(), (request, response) => {
  const contract_id = request.body.data.attributes.ids[0];
  const body = {
    letter: {
      contract_id,
      letter_model_id: 1
    }
  };

  axios.post(`${API_URL}/forest_admin/letters`, body, {
    headers: {
      'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
      'X-CURRENT-USER-EMAIL': request.user.email,
    }
  }).then(res => {

    // response.setHeader('Content-Type', 'application/vnd.oasis.opendocument.text');
    // response.setHeader('Transfer-Encoding', 'chunked');
    // // response.setHeader('Connection', 'keep-alive');
    // response.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
    // response.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
    // response.setHeader('Content-Disposition', 'attachment; filename="blank_letter_so.odt"');
    // response.setHeader('Content-Transfer-Encoding', 'binary');

    // response.set({ ...res.headers });
    response.send(res.data);

  }).catch(err => {
    response.status(400).send({ error: err.response.data.error.message });
  });
});

My API provider is sending me a binary odt file which I’d like to send back to Forest Admin.

I have tried basically all combinations of headers settings before send() (all the comments above). At the very best, I receive a corrupted unreadable file. I’ve been trying to copy the response headers as well : response.set({ ...res.headers });

I’m clearly missing something here, all I want to do is transfer my binary file to my FA front-end.

Note that everything is working fine in Postman.

Hello @JeremyV,

Just to be sure, do you need your Axios call to be a POST and not a GET?
I tried to create a simple file server locally (with the http-server nom package), and if I change axios.post to axios.get in you code sample (and adapt the file URL of course) I can receive a file via my Forest Admin panel.

If changing the post to get is not right, could you tell me what api provider your are using? If they provide a free account I could try to reproduce you issue.

Thank you

Hello @Guillaume_Deslandes

Indeed this is a POST and not a GET :

It might be quite difficult to allow you to test this API since this is in a private domain accessible through VPN… I’ll see what I can do.

Hey @JeremyV,

We have the following example with some static file.

https://docs.forestadmin.com/documentation/reference-guide/actions/create-and-manage-smart-actions#downloading-a-file

But, we don’t have any example with your use case. I’ll try to reproduce your issue.

Best regards,
Morgan

More informations

This is an exemple of the file we are supposed to download :
blank_letter_so.tar (15.5 KB)

This is what we get in FA :
blank_letter_so.tar (40 KB)

(files have been manually archived to be uploaded here)

Hey @JeremyV, I’ll try to reproduce

I just tried and I had no issue. I have the following code:

async function downloadFromGet(request, response) {
  const requestResponse = await superagent.post(`${process.env.API_URL}/download-odt`);


  response.setHeader('content-type', 'application/vnd.oasis.opendocument.text');
  response.setHeader('content-disposition', 'attachment; filename="blank_letter_so.odt"');
  response.setHeader('accept-ranges', 'bytes');

  response.send(requestResponse.body);
}
1 Like

Hi @morganperre @vince
Sorry I had to put this subject on the side for a few weeks.
I managed to get an access for you to test from the real API.
Can you provide an email address where I can share the Postman collection.

Thank you.

Hey @JeremyV,
As I say it works on our side so it must be coming from your code :wink:. Did you try the code above ?

Yes I did. no difference unfortunately. :frowning:

Here it is:

router.post('/actions/generer-un-courrier', permissionMiddlewareCreator.smartAction(), async (request, response) => {
  const contract_id = request.body.data.attributes.ids[0];

  const body = {
    letter: {
      contract_id,
      letter_model_id: 1
  };

  const requestResponse = await axios.post(`${API_URL}/forest_admin/letters`, body, {
    headers: {
      'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
      'X-CURRENT-USER-EMAIL': request.user.email,
    }
  });

  response.setHeader('Content-Type', 'application/vnd.oasis.opendocument.text');
  response.setHeader('Content-Disposition', 'attachment; filename="blank_letter_so.odt"');
  response.setHeader('accept-ranges', 'bytes');
  response.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');

  response.send(requestResponse.data);
});

i’ve got no other options…

Weird. Could you try with superagent instead of axios ?
If that’s still not that this mean the issue come from your url not returning the right format/data

The initial script is still not working. In the mean time I had another case which is basically the same phenomenon.

router.post('/actions/courrier-changement-de-syndic-aux-fournisseurs', permissionMiddlewareCreator.smartAction(), (request, response) => {
  const maintenance_contract_ids = request.body.data.attributes.ids;

  models.maintenanceContracts.findOne({
    where: { id: maintenance_contract_ids[0] }
  }).then(maintenanceContract => {
    const place_id = maintenanceContract.placeIdKey;
    const body = {
      place_id,
      maintenance_contract_ids
    };

    axios.post(`${API_URL}/forest_admin/maintenance_contracts/send_new_management_info`, body, {
      headers: {
        'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`,
        'X-CURRENT-USER-EMAIL': request.user.email,
      }
    }).then(res => {
      response.setHeader('Content-Type', 'application/zip');
      response.setHeader('Content-Disposition', 'attachment; filename="Information de changement de syndic.zip"');
      response.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
      response.send(res.data);
    });
  });
});

In Postman, the zip file I get is 58 kB. In FA, the file I download is 107kB, and is corrupted.

Guys, just to let you know : it’s WORKING with superagent.

Don’t ask me why or how.

1 Like