1
votes

I am working with GraphQL and is facing an issue with File Upload. My Node version is v14.16.0

I am getting error as below

Error: Unknown type "Upload". Did you mean "Float"?

Below are the package version installed

Package versions

"dependencies": {
    "apollo-server-express": "^2.23.0",
    "bcryptjs": "^2.4.3",
    "compression": "^1.7.4",
    "consola": "^2.15.3",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "graphql-upload": "^11.0.0",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^5.12.5",
    "nodemon": "^2.0.7",
    "yup": "^0.32.9"
  }

Below is my server setup done with apollo-server-express and graphql-upload package

import express from "express";
import consola from "consola";
import { ApolloServer } from "apollo-server-express";
const { error, success } = consola;
import { PORT } from "./config/index.js";
import { typeDefs, resolvers } from "./graphql/index.js";
import * as AppModels from "./models/index.js";
import compression from "compression";
import { graphqlUploadExpress } from "graphql-upload";
//Initialize the app
const app = express();
app.use(compression());
app.use(
  graphqlUploadExpress({
    maxFileSize: 30000000,
    maxFiles: 20,
  })
);

const server = new ApolloServer({
  typeDefs,
  resolvers,
  uploads: false,
  context: {
    ...AppModels,
  },
});
app.use(express.static("public"));

server.applyMiddleware({ app });
app.listen(PORT, () => {
  success({
    badge: true,
    message: `Server started at ${PORT}`,
  });
});

Here are my type definition for imageUpload Mutation

import { gql } from "apollo-server-express";
export default gql`
  extend type Mutation {
    imageUploader(file: Upload!): String!
  }
`;

My resolver looks like this

import { createWriteStream } from "fs";
import { parse, join } from "path";
import { URL } from "../../config/index.js";
export default {
  Mutation: {
    imageUploader: async (_, { file }) => {
      let { filename, createReadStream } = await file;
      let stream = createReadStream();
      let { name, ext } = parse(filename);
      name = name.replace(/([^a-z0-9 ]+)/gi, "-").replace(" ", "_");
      let serverFile = `D:/${name}${ext}`;
      let writeStream = await createWriteStream(serverFile);
      await stream.pipe(writeStream);
      //serverFile = `${URL}/${serverFile.split("uploads")[1]}`;
      return serverFile;
    },
  },
};
1

1 Answers

2
votes

Well this is for anybody who faces the situation

As we are using the graphl-upload package so we need to define the custom scalar in typedef and assign the Upload type in resolver.

So now my typedef looks like this. Notice the code scalar Upload

import { gql } from "apollo-server-express";
export default gql`
  scalar Upload
  extend type Mutation {
    imageUploader(file: Upload!): String!
  }
`;

After typedef changes we need to define a resolver for that scalar. So now the resolver looks like this

import { createWriteStream } from "fs";
import { GraphQLUpload } from "graphql-upload";
import { parse, join } from "path";
import { URL } from "../../config/index.js";
export default {
  Upload: GraphQLUpload,
  Mutation: {
    imageUploader: async (_, { file }) => {
      let { filename, createReadStream } = await file;
      let stream = createReadStream();
      let { name, ext } = parse(filename);
      name = name.replace(/([^a-z0-9 ]+)/gi, "-").replace(" ", "_");
      let serverFile = `D:/${name}${ext}`;
      let writeStream = await createWriteStream(serverFile);
      await stream.pipe(writeStream);
      //serverFile = `${URL}/${serverFile.split("uploads")[1]}`;
      return serverFile;
    },
  },
};

Above code helped me in getting pass that issue.