Upload value invalid using graphql-upload when trying to upload image from client side

Viewed 321

I'm trying to use the graphql-upload library to upload an image to the local project directory. I'm using type-graphql, express, react and apollo.

I've set the variable uploads: false in the ApolloServer:

const apolloServer = new ApolloServer({
    schema,
    introspection: true,
    playground: true,
    tracing: true,
    uploads: false
});

And specified the max file size and quantity using:

app.use(graphqlUploadExpress({
    maxFileSize: 10000000,
    maxFiles: 20,
}));

I created the mutation in the express backend, using type-graphql, like this:

  @Mutation(() => Boolean)
  async addImagen(@Arg("imagen", () => GraphQLUpload)
  {
    filename,
    createReadStream
  }: Upload): Promise<Boolean> {
    let fileURL = __dirname + `/../../../../admin/src/assets/imagenes/tiendas/${filename}`;
    return new Promise(async (resolve, reject) =>
      createReadStream()
        .pipe(createWriteStream(fileURL))
        .on("finish", () => resolve(true))
        .on("error", () => reject(false))
    );
  }

And created the Upload type in a new file:

import { Stream } from 'stream'

export interface Upload {
  filename: string
  mimetype: string
  encoding: string
  createReadStream: () => Stream
}

Everything is working when using Postman. I followed the guide that specified how to do it and it works.

Working in Postman

But when I try to create a Form in the front end that sends an image in a 'Tienda' form using this mutation:

mutation createTienda($tienda: AddTiendaInput!, $imagen: Upload!) {
    createTienda(tienda: $tienda, imagen: $imagen) {
      _id
      ...
    }
  }

And this resolver:

@Mutation(() => Tienda, { description: 'Crear Tienda' })
  async createTienda(
    @Arg('tienda') tienda: AddTiendaInput,
    @Arg("imagen", () => GraphQLUpload){ filename, createReadStream }: FileUpload
  ): Promise<Tienda> {
     // stuff to create a Tienda
  }

When sending the files from the front end, I get this error:

Variable \"$imagen\" got invalid value { path: \"de3.png\", preview: \"blob:http://localhost:3000/ce88513c-58c4-460c-bed1-460b46db1a43\" }; Upload value invalid..

I've searched everywhere, and nowhere I've found someone using an actual Form Data sent to the server and trying to send the file. The closest thing I've seen is using postman, which I already did and works. But not when sending files from a form to the server.

This is the console.log for the file:

File {path: "de3.png", preview: "blob:http://localhost:3000/ce88513c-58c4-460c-bed1-460b46db1a43", name: "de3.png", lastModified: 1629497721375, lastModifiedDate: Fri Aug 20 2021 17:15:21 GMT-0500 (Ecuador Time), …}
lastModified: 1629497721375
lastModifiedDate: Fri Aug 20 2021 17:15:21 GMT-0500 (Ecuador Time) {}
name: "de3.png"
path: "de3.png"
preview: "blob:http://localhost:3000/ce88513c-58c4-460c-bed1-460b46db1a43"
size: 30104
type: "image/png"
webkitRelativePath: ""
[[Prototype]]: File

And this is the request payload:

{
    "operationName": "createTienda",
    "variables": {
        "tienda": {
            ...
        },
        "imagen": {
            "path": "de3.png",
            "preview": "blob:http://localhost:3000/ce88513c-58c4-460c-bed1-460b46db1a43"
        }
    },
    "query": "mutation createTienda($tienda: AddTiendaInput!, $imagen: Upload!) {\n  createTienda(tienda: $tienda, imagen: $imagen) {\n    _id\n   ...  __typename\n  }\n}\n"
}

I'm not sure why the file is being sent to the server with only the path and preview fields when the log shows six more.

So my question is: What should I do to send the correct type of file to the resolver?

0 Answers
Related