0

I need to read a locally stored image, embed the image to a form with form-data using the GraphQL multipart request specification, then perform a POST request to a graphql server with the body of the request being the form data itself.

I read the image using fs.readFile, and use the data as an argument to my post data function:

fs.readFile('./location/to/image/image.jpg', (err, data) => {
    if (err) {
        throw (err);
    }

    postData(data);
});

My postData function goes as follows:

function postData(readable) {
    /** Create form data */
    const requestBody = new FormData();

    /** Define the query */
    const sdl = `
        mutation ($image: Upload!) {
            testUpload(image: $image){
            code
            success
            message
            }
        }
    `;

    /** Follow instructions according to graphql multipart request specification 
     * https://github.com/jaydenseric/graphql-multipart-request-spec */
    requestBody.append(
        'operations',
        JSON.stringify({
            query: sdl,
            variables: { image: null },
        })
    );

    requestBody.append(
        'map',
        JSON.stringify({
            0: ['variables.image'],
        })
    );

    requestBody.append('0', readable);

    /** Submit the form */
    return new Promise((resolve, reject) => {
        requestBody.submit('http://localhost:4000/api/graphql', (err, res) => {
            if (err) {
                console.error(err);
                reject(err);
            } else {
                let body = '';
                res.on('readable', () => {
                    body += res.read();
                });

                res.on('end', () => {
                    resolve(JSON.parse(body));
                });
            }
        });
    });
}

What happens is, I successfully hit my API and my resolver, but the file's mimetype is received as application/octet-stream.

I am assumming that I am not reading the data correctly, or something else entirely.

I would truely appreciate any help. Thank you.

momomo
  • 319
  • 1
  • 5
  • 15
  • `application/octet-stream` is the generic mimetype for a binary file which a jpeg file is. If the server needs the more specific `image/jpeg` mimetype you might be able to achieve that by putting the read in file data into a blob and set the mime there, eg `new Blob([readable],{type:'image/jpeg'})` and append that – Patrick Evans Nov 14 '21 at 17:04
  • @PatrickEvans I researched more about Blob and Buffers. Apparently, blobs aren't available in node js, and when I use Buffer.from() I get the exact same response (whichis application/octet-stream). Could I ask you for a little more assistance on how to convert it to a blob? – momomo Nov 14 '21 at 18:03
  • There is an experimental Blob api through Buffer, [`buffer.Blob([readable],{type:'image/jpeg'})`](https://nodejs.org/api/buffer.html#class-blob), or depending on the module you are using to get `FormData` might also implement a Blob api, formdata-node seems to: [`import {FormData, Blob} from "formdata-node"`](https://www.npmjs.com/package/formdata-node) – Patrick Evans Nov 14 '21 at 18:30
  • @PatrickEvans I could not understand how to get the node one to work, and for the latter package the FormData.submit method cannot be read on this package. I am slowly starting to understand more on how blob/buffer and application/octet-stream data types work, and I can see the file reaching me in the server. I just need to understand how a normal graphql client (like apollo) sends image data, and/or how apollo-upload handles the incoming data. – momomo Nov 14 '21 at 18:42
  • I found a possible solution using the File constructor [link](https://developer.mozilla.org/en-US/docs/Web/API/File/File) but that constructor is not available in nodejs and I could not find a similar library for it – momomo Nov 14 '21 at 18:49

0 Answers0