【问题标题】:Unknown type "Upload" - Apollo Server Express with graphql-upload Node 14未知类型“上传” - 带有 graphql-upload 节点 14 的 Apollo Server Express
【发布时间】:2021-07-16 07:20:21
【问题描述】:

我正在使用 GraphQL,但遇到了文件上传问题。我的 Node 版本是 v14.16.0

我收到如下错误

错误:未知类型“上传”。您指的是“浮动”吗?

下面是安装的包版本

软件包版本

"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"
  }

下面是我使用 apollo-server-express 和 graphql-upload 包完成的服务器设置

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}`,
  });
});

这是我对 imageUpload Mutation 的类型定义

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

我的解析器看起来像这样

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;
    },
  },
};

【问题讨论】:

    标签: node.js graphql apollo-server express-graphql


    【解决方案1】:

    我正在使用 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
      }
    });
    

    之后,在typeDefs中,

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

    之后,在 解析器

    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链接

    【讨论】:

      【解决方案2】:

      这适用于任何面临这种情况的人

      由于我们使用的是 graphl-upload 包,所以我们需要在 typedef 中定义自定义标量并在解析器中分配 Upload 类型。

      所以现在我的 typedef 看起来像这样。注意代码scalar Upload

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

      在 typedef 更改后,我们需要为该标量定义一个解析器。所以现在解析器看起来像这样

      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;
          },
        },
      };
      

      以上代码帮助我解决了这个问题。

      【讨论】:

      • 我没有在文件中获取 createReadStream。我正在获取文件名
      猜你喜欢
      • 1970-01-01
      • 2019-10-18
      • 2020-03-11
      • 2021-04-20
      • 2019-09-01
      • 2021-10-03
      • 2020-03-05
      • 2020-02-23
      • 2019-04-30
      相关资源
      最近更新 更多