How to use "res.send() of Express" in Meteor solution/method?

I try to use XlsxPopulate to generate excel file.
How to download excel file in XlsxPopulate doc:

router.get("/download", function (req, res, next) {
    // Open the workbook.
    XlsxPopulate.fromFileAsync("input.xlsx")
        .then(workbook => {
            // Make edits.
            workbook.sheet(0).cell("A1").value("foo");
            
            // Get the output
            return workbook.outputAsync();
        })
        .then(data => {
            // Set the output file name.
            res.attachment("output.xlsx");
            
            // Send the workbook.
            res.send(data);
        })
        .catch(next);
});

Please help for Meteor Solution/Method???

Use Picker: https://github.com/meteorhacks/picker

Thanks for your reply.
Now I base on Vue, and use Method
Have any solution on Meteor method

// Method
    writeExcel(){
        if (!this.isSimulation) {
             XlsxPopulate.fromBlankAsync()
                .then(workbook => {
                    // Modify the workbook.
                    workbook.sheet("Sheet1").cell("A1").value("This is neat!");

                    // Write to file.
                    return workbook.outputAsync();
                });
------------------
// Client
            handleWrite(){
                Meteor.call('writeExcel', function (err, result) {
                    // how to donwload...


sorry I haven’t done that but maybe this could be helpful: Fibers and meteor-promise npm pacakge

This is how I turn my res into the download:

const buf = new ArrayBuffer(res.length);
const view = new Uint8Array(buf);
for (let i = 0; i !== res.length; i += 1) view[i] = res.charCodeAt(i) & 0xFF;
const blob = new Blob([buf], {
  type: 'application/octet-stream',
});
// Automatically download the file by appending an a element,
// 'clicking' it, and removing the element
const a = window.document.createElement('a');
a.href = window.URL.createObjectURL(blob, {
  type: 'data:attachment/xlsx',
});
a.download = 'Data.xlsx';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);

@vigorwebsolutions, could your show more detail?
Could I put it in Method or Method Call, please?

Meteor.call('writeExcel', function (err, result) {
  // My code should work here, assuming you are handling your async properly
});

It mean that

// Server
Meteor.methods({
       async writeExcel(){
           let wb = await XlsxPopulate.fromBlankAsync();
           wb.sheet("Sheet1").cell("A1").value("This is neat!");
           return wb.outputAsync();
      }
});
-----------
handleDownload(){
    Meteor.call('writeExcel', function (err, res) {
        console.log(res);

        const buf = new ArrayBuffer(res.length);
        const view = new Uint8Array(buf);
        for (let i = 0; i !== res.length; i += 1) view[i] = res.charCodeAt(i) & 0xFF;
                  const blob = new Blob([buf], {
                  type: 'application/octet-stream',
        });
        // Automatically download the file by appending an a element,
        // 'clicking' it, and removing the element
        const a = window.document.createElement('a');
        a.href = window.URL.createObjectURL(blob, {
               type: 'data:attachment/xlsx',
        });
        a.download = 'Data.xlsx';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
   }
},

Get error

Haven’t used xlsxpopulate, but from their npm page, this is closer to what you will probably need:

XlsxPopulate.outputAsync()
    .then(function (blob) {
        if (window.navigator && window.navigator.msSaveOrOpenBlob) {
            // If IE, you must uses a different method. 
            window.navigator.msSaveOrOpenBlob(blob, "out.xlsx");
        } else {
            var url = window.URL.createObjectURL(blob);
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.href = url;
            a.download = "out.xlsx";
            a.click();
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
        }
    });

Excuse me, could example code on Method what it return?

I still don’t understand the complete code on Method and Client Call???

I think the issue you may have is that by default outputAsync() returns a blob. You can read more about blobs here:

As far as I can tell, Meteor’s EJSON (which is used to pass data from a method back to the client) doesn’t support blobs.

According to the xlsx-populate docs, you can have outputAsync() return data as a base64 string (which will be returned correctly using EJSON) by using outputAsync('base64'). You should then be able to use something in the client based on the documented example, which is location.href = "data:" + XlsxPopulate.MIME_TYPE + ";base64," + base64;.

In your client code the + base64 would be + res I think.

1 Like

@robfallows, Very thanks now it work fine ::+1:

1 Like