Open linwu-hi opened 1 year ago
文件上传在日常开发中应用很广泛,比如在发微博、发微信朋友圈等操作中都会用到图片上传功能。由于浏览器的安全限制,浏览器不能直接操作文件系统,因此需要通过浏览器暴露出来的统一接口来访问文件,然后将文件内容读取到指定的内存中,并执行提交请求操作,将内存中的文件内容上传到服务端,服务端再解析前端传来的数据信息,最终将文件保存到服务器的文件系统中。
文件上传需要设置请求头为content-type: multipart/form-data,其中multipart表示互联网上的混合资源,即资源由多种元素组成,而form-data表示可以使用HTML Forms和POST方法上传文件。
content-type: multipart/form-data
multipart
form-data
文件上传的请求结构如下:
POST /upload HTTP/1.1 Host: example.com Content-Type: multipart/form-data; boundary=--------------------------1234567890 --------------------------1234567890 Content-Disposition: form-data; name="file"; filename="example.jpg" Content-Type: image/jpeg ... binary data of the image ... --------------------------1234567890--
其中,boundary表示分隔符,用于分隔不同的表单项。每个表单项必须包含Content-Disposition头,其他头信息如Content-Type为可选项。
boundary
Content-Disposition
Content-Type
文件上传可以分为两个步骤:
在前端,我们可以通过HTML的<input type="file">元素来实现文件上传的表单:
<input type="file">
<form action="http://localhost:8080/api/upload" method="post" enctype="multipart/form-data"> <input type="file" name="file" id="file" value="" multiple="multiple" /> <input type="submit" value="提交"/> </form>
在后端,我们可以使用Koa框架中的koa-body中间件来解析上传的文件数据:
koa-body
npm install koa-body
const Koa = require('koa'); const koaBody = require('koa-body'); const app = new Koa(); app.use(koaBody({ multipart: true, formidable: { maxFileSize: 200 * 1024 * 1024 // 设置上传文件大小最大限制,默认2M } })); app.use(async (ctx) => { // 获取上传的文件 const file = ctx.request.files.file; // 创建可读流 const reader = fs.createReadStream(file.path); let filePath = path.join(__dirname, 'public/upload/') + `/${file.name}`; // 创建可写流 const upStream = fs.createWriteStream(filePath); // 可读流通过管道写入可写流 reader.pipe(upStream); ctx.body = "上传成功!"; }); app.listen(8080, () => { console.log('Server started on http://localhost:8080'); });
在服务器端,我们需要将上传的文件进行解析,保存到指定的目录中。在上述代码中,我们通过使用fs模块来处理文件的保存操作。
fs
除了使用koa-body,我们还可以使用koa-multer中间件来实现文件上传:
koa-multer
npm install koa-multer
const Koa = require('koa'); const Router = require('koa-router'); const multer = require('koa-multer'); const path = require('path'); const app = new Koa(); const router = new Router(); const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, "./upload/") }, filename: (req, file, cb) => { cb(null, Date.now() + path.extname(file.originalname)) } }) const upload = multer({ storage }); router.post("/upload", upload.single('file'), (ctx, next) => { console.log(ctx.req.file); // 获取上传文件 }) app.use(router.routes()); app.listen(8080, () => { console.log('Server started on http://localhost:8080'); });
以上代码中,我们使用multer中间件来实现文件上传,storage选项用于设置文件的保存路径和文件名,upload.single('file')表示只上传单个文件。
multer
storage
upload.single('file')
面试官:如何实现文件上传?说说你的思路
一、什么是文件上传?
文件上传在日常开发中应用很广泛,比如在发微博、发微信朋友圈等操作中都会用到图片上传功能。由于浏览器的安全限制,浏览器不能直接操作文件系统,因此需要通过浏览器暴露出来的统一接口来访问文件,然后将文件内容读取到指定的内存中,并执行提交请求操作,将内存中的文件内容上传到服务端,服务端再解析前端传来的数据信息,最终将文件保存到服务器的文件系统中。
文件上传需要设置请求头为
content-type: multipart/form-data
,其中multipart
表示互联网上的混合资源,即资源由多种元素组成,而form-data
表示可以使用HTML Forms和POST方法上传文件。文件上传的请求结构如下:
其中,
boundary
表示分隔符,用于分隔不同的表单项。每个表单项必须包含Content-Disposition
头,其他头信息如Content-Type
为可选项。二、如何实现文件上传?
文件上传可以分为两个步骤:
1. 文件上传
在前端,我们可以通过HTML的
<input type="file">
元素来实现文件上传的表单:在后端,我们可以使用Koa框架中的
koa-body
中间件来解析上传的文件数据:2. 文件解析
在服务器端,我们需要将上传的文件进行解析,保存到指定的目录中。在上述代码中,我们通过使用
fs
模块来处理文件的保存操作。除了使用
koa-body
,我们还可以使用koa-multer
中间件来实现文件上传:以上代码中,我们使用
multer
中间件来实现文件上传,storage
选项用于设置文件的保存路径和文件名,upload.single('file')
表示只上传单个文件。参考文献