Я хочу загрузить файл через GraphQL и выполнить этот статья.
Вот моя схема:
extend type Mutation {
bannerAdd(
title: String!
image: Upload
): ID
}
Однако, когда я запускаю приложение, это дает мне эту ошибку:
Unknown type "Upload". Did you mean "Float"?
Следуя приведенной выше статье, сервер Apollo автоматически генерирует скаляр загрузки, но почему это происходит?
Также определите скаляр загрузки вручную, который также не работает:
scalar Upload
...
Дает мне эту ошибку:
Error: There can be only one type named "Upload".
Кажется, в моем коде нет ничего плохого. Есть ли что-то, что я пропустил? Используя [email protected], Apollo [email protected], Apollo Server [email protected] и [email protected].
Любой совет будет очень признателен.





Вот решение, которое я сделал, добавив собственный скаляр с именем «FileUpload» и добавив GraphQLUpload в качестве распознавателя, например:
import { GraphQLUpload } from 'graphql-upload';
export const resolvers = {
FileUpload: GraphQLUpload
};
Это прекрасно работает, но это может быть не идеальное решение. Надеюсь, Аполлон скоро это исправит.
P.S. Чтобы загрузить файл из вашего браузера, вам также необходимо правильно установить ссылку для загрузки в 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 »?»
Эта проблема может быть вызвана передачей исполняемой схемы (опция schema) при инициализации вашего сервера вместо более нового API передачи typeDefs и resolvers по отдельности.
Старый:
const server = new ApolloServer({
schema: makeExecutableSchema({ typeDefs, resolvers })
})
Новый:
const server = new ApolloServer({
typeDefs,
resolvers,
})
Или как описано в документы:
Note: When using typeDefs, Apollo Server adds
scalar Uploadto 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.
Исправьте эту проблему с помощью GraphQLUpload сервера Apollo для создания пользовательского скаляра с именем FileUpload.
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.info(`? Server ready at ${url}`);
});
Вам также необходимо установить пакет аполлон-загрузить-клиент.
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')
);
Пожалуйста, отредактируйте свой вопрос, чтобы включить конфигурацию ApolloServer.