首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NodeJS无法从busboy finish事件返回数据

NodeJS无法从busboy finish事件返回数据
EN

Stack Overflow用户
提问于 2022-06-28 16:50:04
回答 1查看 144关注 0票数 0

我目前正在尝试开发一个google云功能来解析多部分文件(excel格式或csv),以填充防火墙数据库。

我在帮助函数中使用busboy解析文件,将其转换为json并将其返回到主函数。

在我试图返回解析的数据之前,一切都进行得很顺利。我认为最符合逻辑的方法是从busboy 'finish‘事件返回数据,但它似乎不返回数据,因为一旦返回主函数,它就没有定义。我第一次想到了一些与异步代码执行有关的问题,但当我试图只在busboy finish事件中打印数据时,它正常工作。

我试图在网上找到一些相关的内容,但不幸的是没有成功。下面是我的助手函数:

代码语言:javascript
复制
// Takes a multipart request and sends back redable data
const processRequest = (req) => {
    const busboy = Busboy({headers: req.headers});

    formats = ['application/vnd.ms-excel', 'text/csv', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];

    var finalData;
        
    // fieldname is the request key name of the file
    // file is the stream 
    // fname is the name of the fileq
    busboy.on('file', (fieldname, file, fname) => {
        
        // Checks if file is right format
        if(!formats.includes(fname.mimeType)) throw new FileFormatError('File must be excel or csv');

        bytes = [];

        // Checks that the request key is the right one
        if(fieldname == 'file') {

            // Data is the actual bytes, adds it to the buffer each time received
            file.on('data', (data) => {
                bytes.push(data);
            });
            
            // Concatenates the bytes into a buffer and reads data given mimetype
            file.on('end', async () => {
                buffer = Buffer.concat(bytes);
                
                if(fname.mimeType === 'application/vnd.ms-excel' ||
                    fname.mimeType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
                    workbook = XLSX.read(buffer, {type: 'buffer'});
                    json = excelToJson(workbook);
                    console.log(json);
                    finalData = json;
                }

                if (fname.mimeType === 'text/csv') {
                    var csv = [];
                    const stream  = Readable.from(buffer.toString());
                    stream.pipe(CSV.parse({delimiter: ','}))
                    .on('error', (err) => {
                        console.log('csv parsing error');
                        console.log(err.message);
                    }).on('data', (row) => {
                        csv.push(row);
                    }).on('end', () => {
                        console.log('csv file properly processed');
                        console.log(csv);
                        // CSV PARSING LOGIC TO COME, JUST TESTING RIGHT NOW
                        finalData = csv;
                    });
                    
                } 
            });

        }
    });

    busboy.on('finish', () => {
        console.log('busboy finished');
        return finalData;

        // WHEN ONLY PRINTED THE DATA IS PRESENT AND DISPLAYS PROPERLY HERE
    })

    // Processes request body bytes
    busboy.end(req.rawBody);
}

我一定有一些误解,但到目前为止,我还不能指出什么。

提前谢谢您的时间:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-28 17:11:09

您并不是在等待CSV解析真正完成。

最好将异步代码重构为使用async/await

由于您使用的库可能只支持回调样式的异步,所以您需要自己执行一些new Promise包装。

可以理解,我还没有测试下面的代码,但是像这样的东西.

代码语言:javascript
复制
/**
 * Parse the given buffer as a CSV, return a promise of rows
 */
function parseCSV(buffer) {
  return new Promise((resolve, reject) => {
    const csv = [];
    const stream = Readable.from(buffer.toString());
    stream
      .pipe("text/csv".parse({ delimiter: "," }))
      .on("error", reject)
      .on("data", (row) => csv.push(row))
      .on("end", () => resolve(csv));
  });
}

/**
 * Parse the given buffer as a spreadsheet, return a promise
 */
async function parseSpreadsheet(mimeType, buffer) {
  if (
    mimeType === "application/vnd.ms-excel" ||
    mimeType === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  ) {
    const workbook = XLSX.read(buffer, { type: "buffer" });
    return excelToJson(workbook);
  }
  if (mimeType === "text/csv") {
    return parseCSV(buffer);
  }
  throw new Error(`Unknown mime type ${mimeType}`);
}

/**
 * Get the bytes of the field `fieldName` in the request.
 */
function getFileFromRequest(req, fieldName) {
  return new Promise((resolve, reject) => {
    const busboy = Busboy({ headers: req.headers });
    busboy.on("file", (name, file, info) => {
      // Only process the field we care about
      if (name != fieldName) {
        return;
      }
      const bytes = [];
      file.on("data", (data) => bytes.push(data));
      file.on("end", () =>
        resolve({
          info,
          buffer: Buffer.concat(bytes),
        }),
      );
      file.on("error", reject);
    });
    busboy.end(req.rawBody);
  });
}

async function parseRequest(req) {
  // (1) Get the file as a buffer
  const { info, buffer } = await getFileFromRequest(req, "file");
  // (2) Try parsing it as a spreadsheet
  const data = await parseSpreadsheet(info.mimeType, buffer);
  // (3) Do something with the data?
  return data;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72790397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档