无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件

Posted

技术标签:

【中文标题】无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件【英文标题】:Not able to upload files above 1MB using apollo-server-micro & NextJS 【发布时间】:2021-05-27 05:01:17 【问题描述】:

希望您能帮助我解决以下问题。我正在尝试通过首先将文件转换为 DataURL,然后将其作为字符串发送,将 ≈3MB 的 excel 文件从客户端上传到 API。这适用于较小的文件,但它似乎以某种方式阻止了我的较大文件。

当我上传文件时,我收到以下错误。

POST body missing. Did you forget use body-parser middleware?

我进行了自己的研究,发现更多人有同样的问题,但我找不到解决方案。 https://github.com/apollographql/apollo-server/issues/792

这是我在服务器端使用的代码。

import  ApolloServer, gql  from 'apollo-server-micro'

type Props = 
    _id: string
    file: string[]


const typeDefs = gql`
    type Mutation 
        uploadFile(file: [String!]!): Boolean!
    
    type Query 
        readUpload(_id: String!): Boolean!
    
`

const resolvers = 
    Mutation: 
        async uploadFile(_: any,  file : Props)    
            console.log(file)
            
            return true
        
    ,
    Query: 
        async readUpload(_: any,  _id : Props) 
        
    


const apolloServer = new ApolloServer( 
    typeDefs, 
    resolvers
)

export const config = 
    api: 
        bodyParser: false
    


// Ensure to put a slash as the first character to prevent errors.
export default apolloServer.createHandler( path: '/api/uploads' )

这是我在客户端使用的代码。

import  useRef  from 'react'

import  uploadFile  from '../graphql/fetchers/uploads'
import  UPLOAD_FILE_QUERY  from '../graphql/queries/uploads'

export default function Upload() 
    const inputElement = useRef<htmlInputElement>(null)

    const submitForm = (event: any) => 
        event.preventDefault()
        const files = inputElement.current?.files

        if (files) 
            const fileReader = new FileReader()

            fileReader.onload = async () => 
                try 
                    const result = fileReader.result as string
                    try 
                        console.log(result)
                        await uploadFile(UPLOAD_FILE_QUERY,  file: result )  
                     catch(error) 
                        console.log(error)
                               
                 catch(error) 
                    console.log(error)
                
            
            fileReader.readAsDataURL(files[0]) 
        
    

    return (
        <form>
            <input ref=inputElement type='file'></input>
            <button onClick=(event) => submitForm(event)>Submit</button>
        </form>
    )
 

【问题讨论】:

【参考方案1】:
export const config = 
    api: 
        bodyParser: false
    

将 bodyParser 设置为 true

【讨论】:

【参考方案2】:

您尝试在 json 中将文件作为字符串发送?我认为您应该在客户端使用多部分/表单数据,并在服务器端使用特殊的中间件解析它们 在客户端特殊链接将请求转换为 multipart/formdata 完整示例https://github.com/jaydenseric/apollo-upload-examples

import  useMemo  from "react"
import  ApolloClient, createHttpLink, InMemoryCache  from "@apollo/client"
import  setContext  from "@apollo/client/link/context"
import  getUserTokenFromLocalStorage  from "../utils/utils"
import  createUploadLink  from "apollo-upload-client"
let apolloClient

const httpLink = createUploadLink(
  uri: "/api/graphql",
  headers: 
    "keep-alive": "true",
  ,
)

const authLink = setContext((_,  headers ) => 
  let token = getUserTokenFromLocalStorage()
  return 
    headers: 
      ...headers,
      authorization: token ? `Bearer $token` : "",
    ,
  
)

function createIsomorphLink() 
  if (typeof window === "undefined") 
    const  SchemaLink  = require("@apollo/client/link/schema")
    const  schema  = require("./schema")
    return new SchemaLink( schema )
   else 
    return authLink.concat(httpLink)
  


function createApolloClient() 
  return new ApolloClient(
    s-s-rMode: typeof window === "undefined",
    link: createIsomorphLink(),
    cache: new InMemoryCache(),
  )


export function initializeApollo(initialState = null) 
  const _apolloClient = apolloClient ?? createApolloClient()

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // gets hydrated here
  if (initialState) 
    _apolloClient.cache.restore(initialState)
  
  // For SSG and s-s-r always create a new Apollo Client
  if (typeof window === "undefined") return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

  return _apolloClient


export function useApollo(initialState) 
  const store = useMemo(() => initializeApollo(initialState), [initialState])
  return store

【讨论】:

以上是关于无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件的主要内容,如果未能解决你的问题,请参考以下文章

更新到 nextjs 11 后的 Micro MODULE_NOT_FOUND

SQL Server 2000无法使用

无法访问您试图使用的功能所在的网络位置

无法使用 StorageClass 配置卷 - 无法获取存储帐户的存储密钥

Worklight Studio 和本地开发,有时无法使用 Java 类,有时无法使用 HTML 文件

ADB无法使用解决办法