简体   繁体   中英

Nodejs Missing Data From HTTP Request

I am currently trying to get a file from a HTTP request and then write the data to a file (in this case a PDF).

Using the following I can generate a valid PDF but the file I send has a few lines but the file I create is blank.

The function I am using to try and get the data:

async function getDataFromReq(req){
    let body = '';
    await req.on('data', (chunk) => {
        body += chunk;
    });
    return body;
}

My implementation of that function and writing it to a file:

let file = await getDataFromReq(req);
await writeFile(fileName,file);

My write file function:

async function writeFile(fileName,file){
    fs.writeFileSync('./'+fileName, file);
}

Note:

I was able to use King Friday's solution but I took Quentins's advice and used existing libraries to do the task instead of reinventing the wheel. I used multer following this guide - https://bezkoder.com/node.js-express-file-upload/

  • You can only usefully await a promise
  • req.on does not return a promise

You need to:

  1. Get rid of await inside getDataFromReq
  2. Get rid of async from the declaration of getDataFromReq (it is pointless unless you use await inside it)
  3. Explicitly return a new Promise from getDataFromReq
  4. Register a handler for when the incoming data has finished coming in ( req.on('end', ... ).
  5. resolve the promise inside that handler

However, it would probably be easier to not reinvent wheels. There are already promise based modules for reading files and making HTTP requests .

Like so

const { promises as fs } = require('fs');

function getDataFromReq(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', chunk => {
      body += chunk;
    });
    req.on('end', () => {
      resolve(body);
    });
    req.on('error', err => {
      reject(err);
    });
  });
});

Then you can use in an async method like so...

const body = await getDataFromReq(req);
await fs.writeFile(fileName, body);

Adding to King Friday's answer above, what helped me in getting a pdf file from an HTTP request was adding this line in the event 'data' :

body += Buffer.from(chunk).toString('base64');

Before, I was instead collecting the request information in an array and converting the body in the end function to a base64 string. That was giving me the same result, a blank pdf. However, switching it to be a string, and concatenating the chunks of data while also converting each chunk to a base64 string fixed the problem. Full code example:

function getPdfFromRequest(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', chunk => {
      body += Buffer.from(chunk).toString('base64');
    });
    req.on('end', () => {
      resolve(body);
    });
    req.on('error', err => {
      reject(err);
    });
  });
});

Update: The previous solution I recorded above worked only for a pdf that is one page. To solve this issue, instead I changed body to be an array , and in the data callback, I am going through the buffer object and adding each value to the body array. Finally, in the end function I am converting the buffer array to a base64 string.

function getPdfFromRequest(req) {
  return new Promise((resolve, reject) => {
    const body = [];
    req.on('data', chunk => {
      chunk.forEach((data) => body.push(data));
    });
    req.on('end', () => {
      resolve(Buffer.from(body).toString('base64'));
    });
    req.on('error', err => {
      reject(err);
    });
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM