Неизвестный тип «Загрузка» в Apollo Server 2.6

Я хочу загрузить файл через 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].

Любой совет будет очень признателен.

Пожалуйста, отредактируйте свой вопрос, чтобы включить конфигурацию ApolloServer.

Daniel Rearden 03.06.2019 13:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
4 496
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вот решение, которое я сделал, добавив собственный скаляр с именем «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 »?»

Ikeem Wilson 10.07.2020 17:16

Эта проблема может быть вызвана передачей исполняемой схемы (опция 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 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.

Исправьте эту проблему с помощью GraphQLUpload сервера Apollo для создания пользовательского скаляра с именем 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.info(`? Server ready at ${url}`);
});

Настройка клиента с помощью Apollo Client и React.js:

Вам также необходимо установить пакет аполлон-загрузить-клиент.

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')
);

Другие вопросы по теме