chugs
chugs

Reputation: 61

nodejs issue sending graphql upload file to service

I'm using graphql-upload to upload a file from a web client to an apollo express server to another server, which is expecting a PUT request with a file for avatarImage.

The file is coming into uploadLogo() correctly. I'm able to save and view it from the express server. When I pass the stream of the file to PUT /avatar, that endpoint doesn't receive it. I've tested sending a file directly to /avatar from the filesystem and can confirm the endpoint is working correctly.

Here is my datasource file where I'm appending the file's createReadStream to the form data and sending that in the fetch put.

class MyAPI extends RESTDataSource {
  async uploadLogo(id, file) {
      const { createReadStream, filename, mimetype } = await file;
      const stream = createReadStream();

      const formData = new FormData();

      formData.append('avatarImage', stream, {
        contentType: mimetype,
        filename
      });

      const headers = formData.getHeaders();

      return this.put('http://localhost:5000/avatar', formData, {headers});
    }
}

What am I missing to send the stream in the form data to this /avatar endpoint?

Upvotes: 1

Views: 858

Answers (1)

aditi
aditi

Reputation: 36

I'm facing this issue too and am unsure if this was the right way to address it. Was not able to find any references/documentation to upload from graphql-server-express to another service using graphql-upload. (spectrum question for reference)

I actually had to write the file to the filesystem as a temporary file and pass the file system read stream to form data in order to make it work. Without the temporary file, somehow the headers are incorrect and to the upstream it looks like content-length goes as 1 or 0 or some strange value.

This is what I did:

// this is a method on our data-source-rest
async uploadSomeFile({ invoices }: { invoices: Promise<FileUpload> }) {
    const { createReadStream: apolloFileStream, mimetype, filename } = await invoices;
    const tempFilename = `/tmp/${Date.now()}/${filename}`;
    const stream = apolloFileStream();
    const wstream = createWriteStream(tempFilename);
    await new Promise((resolve, reject) => {
      stream
        .pipe(wstream)
        .on('finish', () => resolve())
        .on('error', () => reject());
    });
    const rstream = createReadStream(tempFilename);
    const data = new FormData();
    data.append('file', rstream);
    return this.post(`/transactions/upload`, data);
  }

Upvotes: 1

Related Questions