ladjs / superagent

Ajax for Node.js and browsers (JS HTTP client). Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
https://ladjs.github.io/superagent/
MIT License
16.59k stars 1.33k forks source link

Posting multipart/form-data #1520

Open Schwartz10 opened 5 years ago

Schwartz10 commented 5 years ago

Hi, I'm trying to test a route that accepts multipart/form-data. The route works via postman, a node script, and in the browser, but I can't seem to get it to work with supertest (who referred me to the superagent docs).

Here's the code that's working in a simple node script:

  const form = new FormData()
  form.append('entry', fs.createReadStream('./readme.md'))
  await axios.post('http://localhost:3001/api/v0/files/add', form, {
    headers: form.getHeaders()
  })
 // success!

I've tried numerous different strategies with forming a post via supertest:

test('POST file', done => {
  const form = new FormData()
  form.append('entry', fs.createReadStream('./readme.md'))
  request(app)
    .post('/api/v0/files/add')
    .type('form')
    .attach('entry', form)
    .set(form.getHeaders())
    .expect(201, done)
})

I've also tried the above with different variations, like removing .type or .set(headers), still with no luck.

The error seems to be throwing from the busboy lib, which is likely due to the multer lib:

Unhandled error. (Error: Part terminated early due to unexpected end of multipart data
      at node_modules/busboy/node_modules/dicer/lib/Dicer.js:65:36
      at processTicksAndRejections (internal/process/task_queues.js:75:11))Error [ERR_UNHANDLED_ERROR]: Unhandled error. (Error: Part terminated early due to unexpected end of multipart data
      at node_modules/busboy/node_modules/dicer/lib/Dicer.js:65:36
      at processTicksAndRejections (internal/process/task_queues.js:75:11))
      at PartStream.<anonymous> (node_modules/busboy/lib/types/multipart.js:278:17)
      at node_modules/busboy/node_modules/dicer/lib/Dicer.js:65:22

Here's the issue with supertest lib

any ideas what i'm doing wrong? Thanks for any help!

danny-does-stuff commented 4 years ago

@Schwartz10 were you able to get this working? I would love to figure something like this out in my project, but cannot get .attach to work as I expect

MRVDH commented 3 years ago

I'm having the same issue. Sometimes it works, sometimes I get ECONNRESET and sometimes I get ECONNABORTED. It could be related to #747

danny-does-stuff commented 3 years ago

It may be related to this issue as well https://github.com/visionmedia/superagent/issues/1607

denisbilchenko commented 1 year ago

not sure if this is still actual, but anyway I managed to resolve it by creating the file in the server file system, then passing the path to the attach method

const uniqueDir = crypto.randomUUID();
fs.mkdirSync(`/tmp/todownload/${uniqueDir}`);
const localPath = `/tmp/todownload/${uniqueDir}/test.pdf`;
fs.writeFileSync(localPath, Buffer.from('Test pdf file data'), 'binary');

const response = await supertest(app)
      .post('/testingRoute')
      .field('field1', '{ "someProp": "Test" }')
      .field('field2', 'null')
      .attach('file', localPath);

After this multer accepted the file and I could test my code.