Apollo-Server-Express 未收到上传对象

Posted

技术标签:

【中文标题】Apollo-Server-Express 未收到上传对象【英文标题】:Apollo-Server-Express not receiving Upload Object 【发布时间】: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 吗? 【参考方案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-client 的createUploadLink。它可以作为createHttpLink 的替代品,所以只需换掉这些功能就可以了。

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

【讨论】:

以上是关于Apollo-Server-Express 未收到上传对象的主要内容,如果未能解决你的问题,请参考以下文章

res.session 未定义 graphql apollo-server-express

错误:正文必须是字符串。使用 Type-graphql 和 apollo-server-express 时收到: resolvers: [[function HelloResolver]], vali

无法从 apollo-server-express 导入 SchemaDirectiveVisitor

apollo-server-express:如何解决内部订阅问题?

升级到 apollo-server-express 2.0.0 缺少上下文

是否可以将 apollo-server-express 部署到 lambda?