主要参考:
前提:
本文不包含apollo的安装和配置,使用express,安装参考apollo官网的apollo-server-express;
不包含vue的安装和配置,使用vue apollo,安装参考vue apollo官网最后一种手动安装。
这两个官网都不需要翻墙,vue apollo官网自带汉化。
后端(apollo graphql)部分
npm i graphql-upload
typeDefs
// typeDefs
const typeDefs = gql`
type File {
filename: String!
}
type Mutation {
# 上传json
dataUpload(file: Upload!): File!
}`
import { GraphQLUpload } from 'graphql-upload'
const resolvers= {
Upload: GraphQLUpload,
Mutation: {
async dataUpload(parent, { file }) {
const { createReadStream, filename, mimetype, encoding } = await file;
const readStream = createReadStream();
var saveFilename = `${Date.now()}_${filename}`
const savePath = `./src/data/upload-data/${saveFilename}`
// 保存
await new Promise((resolve, reject) => {
// Create a stream to which the upload will be written.
const writeStream = createWriteStream(savePath);
// When the upload is fully written, resolve the promise.
writeStream.on("finish", resolve);
// If there's an error writing the file, remove the partially written file
// and reject the promise.
writeStream.on("error", (error) => {
unlink(savePath, () => {
reject(error);
});
});
// In Node.js <= v13, errors are not automatically propagated between piped
// streams. If there is an error receiving the upload, destroy the write
// stream with the corresponding error.
readStream.on("error", (error) => writeStream.destroy(error));
// Pipe the upload into the write stream.
readStream.pipe(writeStream);
});
console.log("程序执行完毕");
return { filename };
}
}
}
// 将Schema结构的数据转换成GraphQLSchema实例
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
export default schema;
前端(vue)部分
npm i --save apollo-upload-client
组件使用elementui,这里就不写了,直接放script的内容
我的需求是每次只能上传一个文件,不用upload组件的action改成自定义
methods: {
async uploadFun(files) {
var toUploadFile = files.file
// 上传
const result = await this.$apollo
.mutate({
mutation: gql`
mutation dataUploadFun($file: Upload!) {
dataUpload(file: $file) {
filename
}
}
`,
// 参数
variables: {
file: toUploadFile,
},
context: {
hasUpload: true, // Important!
},
})
.then((data) => {
// 结果
console.log(data)
})
.catch((errer) => {
// 错误
console.error(errer)
})
console.log(result)
},
}
正确的Request payload形如(摘自官网):
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="operations"
{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { id } }", "variables": { "file": null } }
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="map"
{ "0": ["variables.file"] }
--------------------------cec8e8123c05ba25
Content-Disposition: form-data; name="0"; filename="a.txt"
Content-Type: text/plain
Alpha file content.
--------------------------cec8e8123c05ba25--
bug
Cannot query field "dataUpload" on type "Mutation"
前端问题,解决:
npm i graphql-tag
在报错页导入:
import gql from 'graphql-tag'
POST body missing, invalid Content-Type, or JSON object has no keys.
后端问题,解决:
// apollo-server的index.js
async function startApolloServer(schema) {
// 与express集成所需的逻辑
const app = express();
app.use(graphqlUploadExpress());// 加上这句话
// ...
}