【问题标题】:Unknown type "Upload" in Apollo Server 2.6Apollo Server 2.6 中的未知类型“上传”
【发布时间】:2019-10-18 19:07:25
【问题描述】:

我想通过 GraphQL 上传文件,并关注了这个article

这是我的架构:

extend type Mutation {
  bannerAdd(
    title: String!
    image: Upload
  ): ID
}

但是当我运行应用程序时,这给了我这个错误:

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

按照上面的文章,Apollo Server 会自动生成 Upload scalar,但是为什么会这样呢?

同时手动定义上传标量也不起作用:

scalar Upload

...

给我这个错误:

错误:只能有一种名为“上传”的类型。

我的代码似乎没有错。有什么我错过的吗?使用 Node@10.14.2、Apollo Server@2.6.1、Apollo Server Express@2.6.1 和 polka@0.5.2。

任何建议都会非常感激。

【问题讨论】:

  • 请编辑您的问题以包含您的 ApolloServer 配置。

标签: node.js graphql apollo-server


【解决方案1】:

使用 Apollo Server 的 GraphQLUpload 修复此问题,以创建一个名为 FileUpload 的自定义标量。

使用 Apollo 服务器设置服务器:

const {ApolloServer, gql, GraphQLUpload} = require('apollo-server');

const typeDefs = gql`
  scalar FileUpload

  type File {
    filename: String!
    mimetype: String!
    encoding: String!
  }

  type Query {
    uploads: [File]
  }

  type Mutation {
    singleUpload(file: FileUpload!): File!
  }
`;

const resolvers = {
  FileUpload: GraphQLUpload,
  Query: {
    uploads: (parent, args) => {},
  },
  Mutation: {
    singleUpload: async (_, {file}) => {
      const {createReadStream, filename, mimetype, encoding} = await file;
      const stream = createReadStream();

      // Rest of your code: validate file, save in your DB and static storage

      return {filename, mimetype, encoding};
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({url}) => {
  console.log(`? Server ready at ${url}`);
});

使用 Apollo 客户端和 React.js 设置客户端:

您还需要安装apollo-upload-client 包。

import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useMutation } from '@apollo/client';
import { createUploadLink } from 'apollo-upload-client';

const httpLink = createUploadLink({
  uri: 'http://localhost:4000'
});

const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache()
});


const UPLOAD_FILE = gql`
  mutation uploadFile($file: FileUpload!) {
    singleUpload(file: $file) {
      filename
      mimetype
      encoding
    }
  }
`;

function FileInput() {
  const [uploadFile] = useMutation(UPLOAD_FILE);

  return (
    <input
      type="file"
      required
      onChange={({target: {validity, files: [file]}}) =>
        validity.valid && uploadFile({variables: {file}})
      }
    />
  );
}

function App() {
  return (
    <ApolloProvider client={client}>
      <div>
        <FileInput/>
      </div>
    </ApolloProvider>
  );
}

ReactDOM.render(
  <React.StrictMode>
    <App/>
  </React.StrictMode>,
  document.getElementById('root')
);

【讨论】:

    【解决方案2】:

    此问题可能是由于在初始化服务器时传递了一个可执行架构(schema 选项)而不是分别传递 typeDefsresolvers 的较新 API。

    旧:

    const server = new ApolloServer({
        schema: makeExecutableSchema({ typeDefs, resolvers })
    })
    

    新:

    const server = new ApolloServer({
        typeDefs,
        resolvers,
    })
    

    或如docs中所述:

    注意:使用 typeDefs 时,Apollo Server 会将 scalar Upload 添加到您的架构中,因此应删除类型定义中任何现有的标量 Upload 声明。如果您使用 makeExecutableSchema 创建架构并使用架构参数将其传递给 ApolloServer 构造函数,请确保包含 scalar Upload

    【讨论】:

      【解决方案3】:

      这是我所做的解决方案,添加名为“FileUpload”的自定义标量并添加 GraphQLUpload 作为解析器,如下所示:

      import { GraphQLUpload } from 'graphql-upload';
      
      export const resolvers = {
        FileUpload: GraphQLUpload
      };
      

      效果很好,但它可能不是完美的解决方案。希望阿波罗能尽快解决这个问题。

      附:要从浏览器上传文件,您还需要在 Apollo Client 中正确设置上传链接。这是我的代码:

      import { ApolloLink, split } from 'apollo-link';
      import { createHttpLink } from 'apollo-link-http';
      import { createUploadLink } from 'apollo-upload-client';
      
      // Create HTTP Link
      const httpLink = createHttpLink({
        uri: ...,
        credentials: 'include'
      });
      
      // Create File Upload Link
      const isFile = value =>
        (typeof File !== 'undefined' && value instanceof File) || (typeof Blob !== 'undefined' && value instanceof Blob);
      const isUpload = ({ variables }) => Object.values(variables).some(isFile);
      const uploadLink = createUploadLink({
        uri: ...
        credentials: 'include'
      });
      
      const terminatingLink = (isUpload, uploadLink, httpLink);
      
      const link = ApolloLink.from([<Some Other Link...>, <Another Other Link...>, terminatingLink]);
      
      const apolloClient = new ApolloClient({
        link,
        ...
      });
      

      【讨论】:

      • 我试过这个并得到以下错误:“结果:失败异常:工作人员无法加载函数graphql:'错误:未知类型“FileUpload”。你的意思是“TokenPayload”吗?'“
      猜你喜欢
      • 2021-07-16
      • 2020-03-05
      • 2019-07-08
      • 2019-04-30
      • 2021-03-02
      • 2021-06-20
      • 2012-04-17
      • 2020-03-20
      • 2021-10-13
      相关资源
      最近更新 更多