Search code examples
javascriptnode.jsmetabase

Create XLSX file from file contents from server and save it


I got Node JS server which gets XLSX file contents from metabase:

app.get('/channels', async (req, res) => {
            // make request to metabase and take response as XLSX
            const queryRequestURL = `${api}/public/card/${cardId}/query/xlsx?parameters=${params}`;
                
        const result = got(queryRequestURL);
                
        res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        res.setHeader("Content-Disposition", "attachment; filename=file.xlsx");
                
        return res.send(res);

        });

It returns file contents like

So when i make request to server and receive response - it comes as file contents above. I need to download this data as ordinary excel file on browser side.

What i've tried:

// make request with typical fetch and get result to res variable.
const filename = 'file.xlsx';
const file = new File(res, filename ,{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});

// create link and click it virtually to download created file
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file);
a.download = filename;
a.click();

But I'm getting the error:

Uncaught (in promise) TypeError: Failed to construct 'Blob': The provided value cannot be converted to a sequence.

I think that I'm doing something wrong and there is more simple way to download file.


Solution

  • As Joey Ciechanowicz mentioned, we should return response.buffer() from backend and work with its data as blob at frontend. I mean

    NodeJS side (using Got):

    const result = got(queryRequestURL, {
            headers: headers
        });
    
        return await result.buffer()
        
    

    Frontend side (pure JavaScript):

    // fetch data
    const result = await fetch(api + path);
    return result.blob();
    
    // download file
    const filename = 'export.xlsx';
    
    var url = window.URL.createObjectURL(result);
    var a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    a.remove();