【问题标题】:Apollo-Server-Express not receiving Upload ObjectApollo-Server-Express 未收到上传对象
【发布时间】:2020-03-05 09:54:22
【问题描述】:

我正在尝试使用 apollo-server-express 和 apollo-client 上传文件。但是,当文件对象传递给解析器时,它始终为空。我可以在客户端看到文件,但在服务器端看不到。我该如何解决这个问题?

我的架构

  type File {
    id: ID
    path: String
    filename: String
    mimetype: String
  }

  extend type Query {
    getFiles: [File]
  }

  extend type Mutation {
    uploadSingleFile(file: Upload!): File
  }

我的解析器

  Mutation: {

    uploadSingleFile: combineResolvers(
      isAuthenticated,
      async (parent, { file }, { models, user, storeUpload }, info) => {
        console.log('Resolver-> uploadSingleFile')
        console.log(file) // Will return empty, { }
        const x = await file
        console.log(x) // Will also return empty, { }
        const storedFile = storeUpload(file)
        return storedFile
      }
    ),

  },

我的客户端查询文件

export const UPLOAD_SINGLE_FILE = gql`
  mutation uploadSingleFile($file: Upload!) {
    uploadSingleFile(file: $file) {
      id
    }
  }
`

我的客户端界面

import React from 'react'

// GQL
import { useApolloClient, useMutation } from '@apollo/react-hooks'
import { UPLOAD_SINGLE_FILE } from '../../queries'

const FileUpload = props => {

  const [uploadSingleFile, uploadSingleFileResult] = useMutation(UPLOAD_SINGLE_FILE, {
    onCompleted(uploadSingleFile) {
      console.log('Completed uploadSingleFile')
    }
  })

  const apolloClient = useApolloClient()

  const handleUploadFile = ({
    target: {
      validity,
      files: [file]
    }
  }) => {
    console.log('Uploading file...')
    if(validity.valid) {
      console.log('Valid')
      console.log(file.name)
      uploadSingleFile({ variables: { file } })
      .then(() => {
        apolloClient.resetStore()
      })
    }
    else console.log('Invalid file')      
  }

  return(
        <input type="file" required onChange={handleUploadFile} />
  )
}

export default FileUpload

更新

我的前端设置是:

const httpLink = createHttpLink({
  uri: 'http://localhost:4000/graphql',
})

const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem('token')
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    }
  }
})

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
})

【问题讨论】:

  • file 是一个 Promise -- 你在等待文档中显示的吗?
  • 我尝试在解析器中等待文件然后显示它,但它仍然显示为空。我在上面添加了显示等待的代码。
  • 你在前端使用the appropriate link
  • 谢谢丹尼尔,我已经添加了我的前端设置。我已经在使用该链接访问 GraphQL 界面并设置标题。当链接字段已被用于其他用途时,还有其他方法可以在该设置中使用 apollo-upload-client 吗?

标签: upload graphql apollo-server


【解决方案1】:

假设您设置并使用了正确的链接(使用 Daniel 在他的帖子中提到的 createUploadLink),一旦您在服务器上的解析器中等待承诺,您应该能够从 file 解构道具。

const { filename, mimetype, createReadStream } = await file.promise;
console.log(filename, mimetype);

// to get a stream to use of the data
const stream = createReadStream();

更新:在最新版本的 graphql-upload 中,您可以像在 OP 中一样等待文件,而不是 file.promise。我似乎使用的是旧版本的 lib。

【讨论】:

    【解决方案2】:

    您需要在 Apollo 客户端中使用适当的 Link 才能启用文件上传。最简单的方法是使用来自apollo-upload-clientcreateUploadLink。它可以作为createHttpLink 的替代品,所以只需换掉这些功能就可以了。

    const httpLink = createUploadLink({
      uri: 'http://localhost:4000/graphql',
    })
    const authLink = ...
    const client = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache(),
    })
    

    【讨论】:

      猜你喜欢
      • 2021-10-22
      • 2021-04-20
      • 2019-09-17
      • 2021-07-16
      • 1970-01-01
      • 2020-08-08
      • 2021-07-31
      • 2019-01-21
      • 2021-12-20
      相关资源
      最近更新 更多