【问题标题】:Not able to upload files above 1MB using apollo-server-micro & NextJS无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件
【发布时间】: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>
    )
} 

【问题讨论】:

    标签: javascript reactjs next.js apollo graphql-js


    【解决方案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({
          ssrMode: 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 SSR 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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 2018-07-30
        • 1970-01-01
        • 1970-01-01
        • 2021-05-18
        • 2016-08-01
        • 1970-01-01
        相关资源
        最近更新 更多