0

I want to attach around 100 files into a POST request using supertest, but I haven't found any way to do this.

const supertest = require('supertest);

const fs = require('fs');
const { promisify } = require('utils');

const request = supertest('http://localhost:3000');

const readdir = promisify(fs.readdir);

(async () => {
  try {
    const files = await readdir(path.resolve(__dirname, '/path/to');
    request
      .post('/upload')
      .attach('file', files)
      .end((response => {
        console.log(response);
      });
  } catch(err) => {
    console.error(err);
  }
)();

Given the following piece of code, the request needs to chain the attach method every time a fileN is wanted to be send in the request, so I want how to attach recursively every file inside the same folder using the fs node core module

  • 1
    Please provide some code example of what you're trying to achieve. – Nino Filiu Feb 22 '19 at 20:30
  • 2
    I made myself a little bit more clear – Benjamín Vázquez Feb 22 '19 at 21:01
  • Get a list of files from fixture directory with `fs`? Possible duplicate of https://stackoverflow.com/questions/2727167/how-do-you-get-a-list-of-the-names-of-all-files-present-in-a-directory-in-node-j – Estus Flask Feb 22 '19 at 21:54
  • @estus Not really the problem, I mean, I already did that, but the goal is how to achieve to pass that array of files in a single HTTP request, AFAIK the docs did not provide a recursively way https://visionmedia.github.io/superagent/#multipart-requests... So I'm hoping one of two things, either someone has already faced this before or the approach is using Promises some way – Benjamín Vázquez Feb 22 '19 at 22:11

2 Answers2

2

supertest extends superagent with testing functionality and works the same way. request.post('/upload') creates request instance and is chainable. Instance methods return an instance itself for chaining:

const requestInstance = request.post('/upload');

requestInstance === requestInstance.attach('file', ...);

supertest and superagent are thenable, it's preferable to chain the result as a promise for correct control flow when it's used with async..await:

  try {
    const files = await readdir(path.resolve(__dirname, '/path/to');
    let requestInstance = request.post('/upload');

    for (const file of files) {
      // no need to reassign requestInstance because it's same instance
      // requestInstance = requestInstance.attach('file', file);
      requestInstance.attach('file', file);
    }

    const response = await requestInstance;
  } catch (err) {
    console.error(err);
  }
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • OMG Dude!!!, I'm won't touch the code in the following hours, but your explanation makes so much sense, I'm pretty sure this will work, when I make the modifications I'll tell you... The use of the await on the instance is the part I was missing – Benjamín Vázquez Feb 22 '19 at 22:37
  • Yes, that a request is thenable is very convenient. If supertest reference is lacking, check superagent docs, the former is a simple wrapper for the latter. Hope this helps. – Estus Flask Feb 22 '19 at 22:38
0

You might just want to make several individual requests with supertest and Promise.all. You can use globby to get a list of files eg. without async might even be more straightforward, unless you need the result somewhere else.

const files = glob(path.resolve(__dirname, '/path/to'));

const requests = files.map((file) => {
    return request
      .post('/upload')
      .attach('file', file)
      .end((response => {
        console.log(response);
      });
});

Promise.all(requests).then(console.log('done')).catch(console.error);
4m1r
  • 12,234
  • 9
  • 46
  • 58