ton1
ton1

Reputation: 7628

How to read file from createReadStream in Node.js?

I have web appication that can upload excel file. If user upload, the app should parse it and will return some rows that file have. So, The application don't need to save file to its filesystem. Parsing file and return rows is a job. But below code, I wrote this morning, it save file to its server and then parse it.. I think it's waste server resource.

I don't know how to read excel file with createReadStream. Without saving file, how can I parse excel directly? I am not familiar with fs, of course, I can delete file after the job finished, but is there any elegant way?

import { createWriteStream } from 'fs'
import path from 'path'
import xlsx from 'node-xlsx'

// some graphql code here... 


async singleUpload(_, { file }, context) {
    try {
    console.log(file)
    const { createReadStream, filename, mimetype, encoding } = await file

    await new Promise((res) =>
        createReadStream()
        .pipe(createWriteStream(path.join(__dirname, '../uploads', filename)))
        .on('close', res)
    )

    const workSheetsFromFile = xlsx.parse(path.join(__dirname, '../uploads', filename))
    for (const row of workSheetsFromFile[0].data) {
        console.log(row)
    }

    return { filename }
    } catch (e) {
    throw new Error(e)
    }
},

Upvotes: 3

Views: 7129

Answers (3)

CheapImpact
CheapImpact

Reputation: 21

you can add an event listener before you pipe the data, so you can do something with your file before it uploaded, it look like this


async singleUpload(_, { file }, context) {
    try {
    console.log(file)
    const { createReadStream, filename, mimetype, encoding } = await file

    await new Promise((res) =>
        createReadStream()
        .on('data', (data)=>{
         //do something with your data/file
        console.log({data})
        //your code here
        })
        .pipe(createWriteStream(path.join(__dirname, '../uploads', filename)))
        .on('close', res)
    )
 
},

you can see the documentation stream node js

Upvotes: 0

Rafi Henig
Rafi Henig

Reputation: 6414

Using express-fileupload library which provides a buffer representation for uploaded files (through data property), combined with excel.js which accepts a buffers will get you there.

see Express-fileupload and Excel.js

// read from a file
const workbook = new Excel.Workbook();
await workbook.xlsx.readFile(filename);
// ... use workbook


// read from a stream
const workbook = new Excel.Workbook();
await workbook.xlsx.read(stream);
// ... use workbook


// load from buffer  // this is what you're looking for
const workbook = new Excel.Workbook();
await workbook.xlsx.load(data);
// ... use workbook

Here's a simplified example:

const app = require('express')();
const fileUpload = require('express-fileupload');
const { Workbook } = require('exceljs');

app.use(fileUpload());

app.post('/', async (req, res) => {
    if (!req.files || Object.keys(req.files).length === 0) {
        return res.status(400).send('No files were uploaded.');
    }
     // The name of the input field (i.e. "myFile") is used to retrieve the uploaded file
    await new Workbook().xlsx.load(req.files.myFile.data)
});

app.listen(3000)

Upvotes: 2

Sachin Sharma
Sachin Sharma

Reputation: 184

var xlsx = require('xlsx')

//var workbook = xlsx.readFile('testSingle.xlsx')
var workbook = xlsx.read(fileObj);

You just need to use xlsx.read method to read a stream of data.

Upvotes: 0

Related Questions