在前端开发中,文件上传是必不可少的功能之一。而在使用GraphQL进行服务端开发时,如何处理文件上传就显得比较困难。但现在,我们可以使用GraphQL的第三方解决方案 Apollo Server,它可以帮助我们方便地处理文件上传。
在本篇文章中,我们将介绍如何在GraphQL中使用File Uploads,一步步学习如何设置环境、定义schema、处理上传文件、以及如何在GraphQL Playground中进行文件上传测试等。
环境设置
在使用Apollo Server之前,需要先安装两个必要的依赖:apollo-server
和graphql-upload
。可以使用以下命令进行安装:
npm install apollo-server graphql graphql-upload
接着,我们需要在Apollo Server中使用graphqlUploadExpress
中间件,具体代码如下:
// javascriptcn.com 代码示例 const { ApolloServer } = require('apollo-server'); const { graphqlUploadExpress } = require('graphql-upload'); const server = new ApolloServer({ // ... 其他配置项 uploads: false, // 关闭文件上传,等待中间件处理 context: async ({ req, res }) => ({ req, res, }), }); server.applyMiddleware({ app, // express app path: '/graphql', }); app.use(graphqlUploadExpress()); // 使用文件上传中间件
这段代码可以实现开启Apollo Server的GraphQL Playground,并使用File Uploads功能。需要注意的是,我们需要在上面代码中关闭uploads
选项,等待中间件进行处理。同时,我们也需要定义context上下文,后面需要使用。
定义Schema
在GraphQL中,我们需要定义Schema来说明我们的数据模型。对于文件上传,我们需要增加对应的自定义类型,用于上传文件和获取上传文件的数据。
// javascriptcn.com 代码示例 const { gql } = require('apollo-server'); const typeDefs = gql` scalar Upload type File { filename: String! mimetype: String! encoding: String! url: String! } type Query { files: [File!]! } type Mutation { singleUpload(file: Upload!): File! multipleUpload(files: [Upload!]!): [File!]! } `; module.exports = typeDefs;
在上面代码中,我们定义了两个mutation,分别是singleUpload
和multipleUpload
,用于上传单个文件和多个文件。同时定义了一个自定义类型Upload
,用于上传文件数据。还需要定义一个自定义类型File
,用于获取上传文件信息。
处理上传文件
在客户端发送上传请求之后,服务端需要对上传的文件进行处理,通过graphql-upload
工具类实现文件的解析和上传。我们需要新建一个用于处理上传文件的resolver函数。
// javascriptcn.com 代码示例 const { createWriteStream } = require('fs'); const { resolve } = require('path'); const { nanoid } = require('nanoid'); const singleUpload = async (_, { file }) => { const { createReadStream, filename, mimetype } = await file; const stream = createReadStream(); const id = nanoid(); const path = resolve(__dirname, `../uploads/${id}-${filename}`); console.log(`文件保存路径 ${path}`); const promise = new Promise((resolve, reject) => stream.pipe(createWriteStream(path)) .on('finish', () => resolve({ id, filename, mimetype, url: `http://localhost:3000/files/${id}` })) .on('error', (e) => { console.log(`文件保存失败 ${e}`); reject(e); }) ); return promise; }; const multipleUpload = async (_, { files }) => { return await Promise.all(files.map(async (file) => await singleUpload(null, { file }))); }; module.exports = { singleUpload, multipleUpload, };
在代码中,我们通过createReadStream
方法获取上传文件的可读流,使用createWriteStream
方法将可读流写入到服务器的磁盘上。最后,将文件信息和路径通过Promise返回给客户端。
需要注意的是,我们在上面的代码中添加了唯一的id作为文件名的标识,这样可以有效地防止文件重复覆盖问题。
测试文件上传
到这一步,我们就实现了文件上传功能,下一步我们需要在GraphQL Playground中进行测试。首先,我们需要在请求头部添加Content-Type: multipart/form-data
,表明上传内容类型是多媒体数据。
接着,我们就可以通过GraphQL Playground进行文件上传测试了。在Playground的左边菜单面板中,选择MUTATION
,并在右边QUERY VARIABLES
中添加如下代码:
{ "file1": null, "files": [null, null] }
在MUTATION
面板中,我们可以使用singleUpload
和multipleUpload
函数进行文件上传操作。具体使用如下:
mutation SingleUpload($file1: Upload!) { singleUpload(file: $file1) { filename mimeType encoding url } }
mutation MultipleUpload($files: [Upload!]!) { multipleUpload(files: $files) { filename mimeType encoding url } }
点击QUERY VARIABLES
中的运行按钮,在弹出的对话框中选择上传的文件,最后点击MUTATION
面板的完成按钮即可提交。
总结
以上就是GraphQL中使用File Uploads的完整指南,我们学习了如何设置环境、定义Schema、处理上传文件、以及在GraphQL Playground中进行文件上传测试等操作。希望本文可以为大家在使用GraphQL进行前端开发时提供有价值的参考。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6545deda7d4982a6ebf87309