如何解决无法使用 apollo-server-micro 和 NextJS 上传 1MB 以上的文件
希望你能帮助我解决以下问题。我试图通过首先将文件转换为 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>
)
}
解决方法
export const config = {
api: {
bodyParser: false
}
}
将 bodyParser 设置为 true
,您尝试在 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
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。