apollo graphql结合vue实现上传文件保存到本地

主要参考: 

https://github.com/jaydenseric/graphql-multipart-request-spechttps://github.com/jaydenseric/graphql-multipart-request-spec

https://github.com/jaydenseric/apollo-upload-clienthttps://github.com/jaydenseric/apollo-upload-client

https://www.apollographql.com/docs/apollo-server/data/file-uploads/icon-default.png?t=M276https://www.apollographql.com/docs/apollo-server/data/file-uploads/ 

前提: 

本文不包含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());// 加上这句话

    // ...

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值