Apollo Server 2.6 中的未知类型 "Upload"
Unknown type "Upload" in Apollo Server 2.6
我想通过 GraphQL 上传文件,然后按照这个 article。
这是我的架构:
extend type Mutation {
bannerAdd(
title: String!
image: Upload
): ID
}
然而,当我 运行 应用程序时,这给了我这个错误:
Unknown type "Upload". Did you mean "Float"?
按照上面的文章,Apollo Server会自动生成Upload scalar,但是为什么会这样呢?
也手动定义上传标量也不起作用:
scalar Upload
...
给我这个错误:
Error: There can be only one type named "Upload".
我的代码似乎没有问题。我错过了什么吗?使用 Node@10.14.2、Apollo Server@2.6.1、Apollo Server Express@2.6.1 和 polka@0.5.2。
如有任何建议,我们将不胜感激。
这是我所做的解决方案,添加名为 "FileUpload" 的自定义标量并添加 GraphQLUpload 作为解析器,如下所示:
import { GraphQLUpload } from 'graphql-upload';
export const resolvers = {
FileUpload: GraphQLUpload
};
效果很好,但可能不是完美的解决方案。希望阿波罗尽快解决这个问题。
P.S。要从浏览器上传文件,您还需要在 Apollo Client 中正确设置 upload link。这是我的代码:
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,
...
});
这个问题可能是由于在初始化服务器时传递了可执行模式(schema
选项)而不是较新的 API 分别传递 typeDefs
和 resolvers
引起的.
旧:
const server = new ApolloServer({
schema: makeExecutableSchema({ typeDefs, resolvers })
})
新:
const server = new ApolloServer({
typeDefs,
resolvers,
})
或如 docs 中所述:
Note: When using typeDefs, Apollo Server adds scalar Upload
to your schema, so any existing declaration of scalar Upload in the type definitions should be removed. If you create your schema with makeExecutableSchema and pass it to ApolloServer constructor using the schema param, make sure to include scalar Upload
.
使用 Apollo Server 的 GraphQLUpload
修复此问题以创建名为 FileUpload
的自定义标量。
使用 Apollo Server 的服务器设置:
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')
);
我想通过 GraphQL 上传文件,然后按照这个 article。
这是我的架构:
extend type Mutation {
bannerAdd(
title: String!
image: Upload
): ID
}
然而,当我 运行 应用程序时,这给了我这个错误:
Unknown type "Upload". Did you mean "Float"?
按照上面的文章,Apollo Server会自动生成Upload scalar,但是为什么会这样呢?
也手动定义上传标量也不起作用:
scalar Upload
...
给我这个错误:
Error: There can be only one type named "Upload".
我的代码似乎没有问题。我错过了什么吗?使用 Node@10.14.2、Apollo Server@2.6.1、Apollo Server Express@2.6.1 和 polka@0.5.2。
如有任何建议,我们将不胜感激。
这是我所做的解决方案,添加名为 "FileUpload" 的自定义标量并添加 GraphQLUpload 作为解析器,如下所示:
import { GraphQLUpload } from 'graphql-upload';
export const resolvers = {
FileUpload: GraphQLUpload
};
效果很好,但可能不是完美的解决方案。希望阿波罗尽快解决这个问题。
P.S。要从浏览器上传文件,您还需要在 Apollo Client 中正确设置 upload link。这是我的代码:
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,
...
});
这个问题可能是由于在初始化服务器时传递了可执行模式(schema
选项)而不是较新的 API 分别传递 typeDefs
和 resolvers
引起的.
旧:
const server = new ApolloServer({
schema: makeExecutableSchema({ typeDefs, resolvers })
})
新:
const server = new ApolloServer({
typeDefs,
resolvers,
})
或如 docs 中所述:
Note: When using typeDefs, Apollo Server adds
scalar Upload
to your schema, so any existing declaration of scalar Upload in the type definitions should be removed. If you create your schema with makeExecutableSchema and pass it to ApolloServer constructor using the schema param, make sure to includescalar Upload
.
使用 Apollo Server 的 GraphQLUpload
修复此问题以创建名为 FileUpload
的自定义标量。
使用 Apollo Server 的服务器设置:
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')
);