hzh-fe

  一般情况下,前端的文件上传一般都是通过form表单的(<input type="file" />)来完成文件的上传,如果使用node中间层完成跨域,文件的上传就需要在node中间层处理成可读流,转成formData完成转发。

 

一、form表单文件上传

  这是最常见的文件上传方式,通过form表单实现,简单实用,设置一下method、enctype、action属性就可以了,多文件上传需要设置multiple属性(部分浏览器支持还是有些问题的)。

1 <form method="post" enctype="multipart/form-data" action="/api/upload">
2     <input type="text" name="username">
3     <input type="password" name="password">
4     <input type="file" name="file">
5     <input type="submit">
6 </form>

 

二、FormData实现文件上传

  FormData对象用以将数据编译成键值对,以便向后台发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。对部分浏览器对multiple属性不支持的情况,可以使用formData的提交方式完成。

1 <!-- 获取上传文件转成formData类型的文件 -->
2 <input multiple id="file" name="file" type="file" />
3 <button id="btn">提交</button>
 1 const oFile = document.getElementById(\'file\')
 2 const oBtn = document.getElementById(\'btn\')
 3 
 4 oBtn.addEventListener(\'click\', () => {
 5     files = oFile.files
 6     const formData = new FormData()
 7     formData.append(\'file\', files[0])
 8     formData.append(\'file1\', files[1])
 9 
10     fetch(\'/api/upload\', {
11         method: "POST",
12         body: formData
13     })
14 })
  • 使用fetch请求不要设置Content-Type,否则无法请求
  • fetch请求默认是不带cookie

 

三、node中间层完成文件上传跨域

  跨域是因为浏览器的同源策略造成,跨域的方法有很多中,这里使用的是node中间层代理完成(服务端之间的请求是不存在跨域问题)。

  node无法直接解析上传的文件,需要引入拓展包connect-multiparty完成,这样就可以拿到文件数据。

  拿到上传文件,需要在node中转发请求后台server,这里的文件不能直接发给后台,需要将上传的文件使用fs.createReadStream转成可读流,同时引入 form-data 包(node环境是没有formData对象的),这样就可以实现node中间层转发文件类型

  node部分代码:

 1 const fs = require(\'fs\')
 2 const path = require(\'path\')
 3 const FormData = require(\'form-data\')
 4 const express = require(\'express\')
 5 const fetch = require(\'node-fetch\')
 6 const router = express.Router()
 7 const multipart = require(\'connect-multiparty\');
 8 var multipartMiddleware = multipart()
 9 
10 router.post(\'/upload\', multipartMiddleware, function (req, res) {
11     // console.log(req.body, req.files);
12 
13     const { path: filePath, originalFilename } = req.files.file
14     const newPath = path.join(path.dirname(filePath), originalFilename)
15 
16     fs.rename(filePath, newPath, function (err) {
17         if (err) {
18             return;
19         }
20         else {
21             const file = fs.createReadStream(newPath)
22             const form = new FormData()
23             form.append(\'file\', file)
24 
25             fetch(\'http://localhost:8080/upload\', {
26                 method: "POST",
27                 body: form
28             })
29         }
30     })
31     res.json({})
32 });
33 
34 module.exports = router; 

 

注意:

  • node无法直接解析上传文件,需要引入npm包connect-multiparty中间件,或者引入npm包multiparty
  • node拿到文件,需要使用fs.createReadStream转成可读流
  • node环境没有formData对象,需要引入npm包form-data
  • fetch请求提交formData数据,不能设置Comtemt-Type

  

  完整的代码请参考 node中间层实现文件上传

 

  如果喜欢请关注我的Github,给个Star吧,我会定期分享一些JS中的知识,^_^

分类:

技术点:

相关文章: