我正在使用 graphql 并尝试从 react 将文件上传到本地主机服务器。
我是从 apollo 服务器官方文档中学习本教程的:Enabling file uploads in Apollo Server
由于某种原因,图像已损坏(为空),我不知道如何修复它。我已经尝试了很多东西,但都没有运气。
此时,我迫切需要任何变通方法或解决方案。
类型定义
const {gql} = require('apollo-server')
module.exports = gql`
type File {
url: String!
filename: String!
mimetype: String!
encoding: String!
}
type Mutation {
uploadFile(file: Upload!): File!
}
`
解析器
const fs = require("fs");
const path = require("path");
module.exports = {
Query: {
test: () => 'Test completed',
files: () => files
},
Mutation: {
uploadFile: async (parent, {file}) => {
const {createReadStream, filename, mimetype, encoding} = await file
const stream = await createReadStream()
const pathName = path.join(__dirname, `../../public/images/${filename}`)
await stream.pipe(fs.createWriteStream(pathName))
return {
filename,
mimetype,
encoding,
url: `http://locahost:5000/images/${filename}`}
},
}
}
Apollo 客户端设置
import React from 'react'
import App from './App'
import ApolloClient from 'apollo-client'
import {InMemoryCache} from 'apollo-cache-inmemory'
import {createUploadLink} from 'apollo-upload-client'
import {ApolloProvider} from '@apollo/react-hooks'
import {setContext} from 'apollo-link-context'
const httpLink = createUploadLink({
uri: 'http://localhost:5000/graphql/'
})
const authLink = setContext(() => {
const token = localStorage.getItem('jwtToken')
return {
headers: {
authorization: token ? `Bearer ${token}` : ''
}
}
})
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
})
export default (
<ApolloProvider client={client}>
<App/>
</ApolloProvider>
)
反应代码本身
import React from 'react'
import {useMutation, gql} from '@apollo/client'
const UPLOAD_FILE = gql`
mutation uploadFile($file: Upload!) {
uploadFile(file: $file) {
url
mimetype
filename
encoding
}
}
`
function UploadForm() {
const [uploadFile] = useMutation(UPLOAD_FILE, {
onCompleted: data => console.log(data)
})
const handleFileChange = e => {
const file = e.target.files[0]
if(!file) return
uploadFile({variables: {file}})
}
return (
<div>
<h2>Upload file</h2>
<input type='file' onChange={handleFileChange}/>
</div>
)
}
export default UploadForm
控制台输出
uploadFile: {…}
__typename: "File"
encoding: "7bit"
filename: "91f29c99.jpg"
mimetype: "image/jpeg"
url: "http://locahost:5000/images/91f29c99.jpg"
UPD:我试过这种方法。现在有时我会得到非空图像,但它们仍然损坏且无法读取。但大多数时候它仍然是空的。
uploadFile: async (_, {file}) => {
const {createReadStream, filename} = await file;
await new Promise((resolve, reject) =>
createReadStream()
.pipe(fs.createWriteStream(path.join(__dirname, `../../public/images/${filename}`))
.on("finish", () => resolve())
.on("error", reject))
)
return {
url
}
},