jaydenseric / graphql-upload

Middleware and a scalar Upload to add support for GraphQL multipart requests (file uploads via queries and mutations) to various Node.js GraphQL servers.
https://npm.im/graphql-upload
MIT License
1.43k stars 132 forks source link

File/Blob data sent as variable does not support inside the resolver #212

Closed mittalyashu closed 4 years ago

mittalyashu commented 4 years ago

I tried sending the File constructor or even tried converting to File object to blob using it inside the mutation as a variable.

But in the I get the data from the resolver in this format:

{ resolve: [Function],
  reject: [Function],
  promise:
   Promise {
     { filename: 'tumblr_d33bd9ecbbd25a9417e96e0c2ae70f17_d068b0da_500.png',
       mimetype: 'image/png',
       encoding: '7bit',
       createReadStream: [Function: createReadStream] } },
  file:
   { filename: 'tumblr_d33bd9ecbbd25a9417e96e0c2ae70f17_d068b0da_500.png',
     mimetype: 'image/png',
     encoding: '7bit',
     createReadStream: [Function: createReadStream] } }

While trying to use this with aws-sdk package, it shows error

[InvalidParameterType: Expected params.documents to be a string, Buffer, Stream, Blob, or typed array object]

I am not sure if the graphql-upload data type is sending the correct data type.

jaydenseric commented 4 years ago

This question is worded in a very confusing way. I'm sure if you follow the setup instructions carefully on the client and server you will be able to get it all working; most of us successfully use the AWS SDK to store uploads.

If you get really stuck, social media or forums are better places to ask for help with your project. As a guess, you haven't setup the Upload scalar correctly in your schema on the server.

In this repo you are always welcome to raise a GitHub issues to report a reproducible bug or request a feature.

mittalyashu commented 4 years ago

My apologies for not providing clear information.

BTW, I have already setup the Upload scalar properly otherwise I wouldn't have got the data in the resolver in the first place.

This is the function which invokes the mutation and pass the File constructor as a variable.

const filePickerPath = e => {
    const file = e.target.files[0]
    uploadImageMutation({
      variables: {
        image: file
      }
    }).then(response => {
      console.log(response);
    }).catch(error => {
      console.log(error);
    });
  }

Inside the resolver uploadImage

const uploadImage = async input => {
  const data = input.image.file

  const date = new Date().getDate()
  const month = new Date().getMonth() + 1
  const year = new Date().getFullYear()
  const path = `images/${year}/${month}/${date}/${data.filename}`

  const buffer = Buffer.from(JSON.stringify(input));

  const params = {
    Bucket: process.env.DO_SPACES_BUCKET,
    Key: path,
    Body: buffer,
    ACL: "public-read"
  };

  spaces.putObject(params, (error, data) => {
    if (error) {
      console.error("Error: uploadImage");
      console.log(error, error.stack);
    }
    else {
      console.log("data");
      console.log(data);
    }
  });
  console.log("Spaces end");
}

When I console log the input argument variable, I get this data-type object.

{ image:
   Upload {
     resolve: [Function],
     reject: [Function],
     promise: Promise { [Object] },
     file:
      { filename: 'tumblr_d33bd9ecbbd25a9417e96e0c2ae70f17_d068b0da_500.png',
        mimetype: 'image/png',
        encoding: '7bit',
        createReadStream: [Function: createReadStream] } } }

After converting this input object to Buffer, it still didn't work. So, I am not sure if I am getting the correct data-type from the graphql-upload package.

NOTE: I even tried following the examples for this https://github.com/jaydenseric/apollo-upload-examples repository, it still didn't help much.

jaydenseric commented 4 years ago

None of that server code looks right. Did you read the instructions?

Inside the resolver uploadImage const uploadImage = async input => {

That is not the signature of a mutation resolver. Mutation arguments are the second function argument. Either your code is wrong, or you are not communicating clearly.

const data = input.image.file

Your mutation argument is called image, so why are you using .file? That's not the GraphQL upload API.

Where are you awaiting the upload, and where are you running createReadStream?

const buffer = Buffer.from(JSON.stringify(input));

Why do you expect to be able to JSON stringify a binary file read stream.

I think you need to go back to the start and read the instructions carefully.