Reputation: 2038
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;
},
},
};
Upvotes: 1
Views: 2300
Reputation: 121
I'm using NODE 14
import {ApolloServer} from "apollo-server-express";
...
// If you want to see uploaded images, then you need to add these commands and,
// create a folder to upload images name like 'uploads'
const app = express();
app.use(express.static(join(__dirname, './uploads')));
app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
const httpServer = http.createServer(app);
const server = new ApolloServer({
uploads: false, // --------- use this
typeDefs,
resolvers,
plugins: [IN_PROD ? ApolloServerPluginLandingPageGraphQLPlayground() :
ApolloServerPluginLandingPageDisabled(),
ApolloServerPluginDrainHttpServer({httpServer})],
context: {
...AppModels
}
});
after that, in typeDefs,
import { gql } from "apollo-server-express";
export default gql`
scalar Upload // ---- use this
extend type Mutation {
imageUploader(file: Upload!): String!
}
`;
after that, In resolvers
import {parse, join} from 'path';
import {createWriteStream} from 'fs';
import {URL} from "../../../config";
import {GraphQLUpload} from "graphql-upload";
export default {
Upload: GraphQLUpload, // ----- use this
Query: {
info: () => "Hello i am image resolver methods."
},
Mutation: {
imageUploader: async (_, {file}) => {
try {
let {
filename,
createReadStream
} = await file;
let stream = createReadStream();
let {
ext,
name
} = parse(filename);
name = name.replace(/([^a-z0-9 ]+)/gi, '-').replace(' ', '_');
let serverFile = join(__dirname,
`../../../uploads/${name}-${Date.now()}${ext}`);
let writeStream = await createWriteStream(serverFile);
await stream.pipe(writeStream);
let lastPath = serverFile.split('uploads')[1];
lastPath = lastPath.replace('\\', '/');
serverFile = `${URL}${lastPath}`;
return serverFile;
} catch (e) {
console.log("ERROR UPLOAD A IMAGE", e);
throw e;
}
}
}
}
Github link
Upvotes: 0
Reputation: 2038
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.
Upvotes: 4