使用原生进行文件上传

from的方式

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <form action="/api/upload" method="POST" enctype="multipart/form-data">
  10. <p>
  11. <input type="text" name="a" />
  12. </p>
  13. <p>
  14. <input type="file" name="img" />
  15. </p>
  16. <p>
  17. <button>提交</button>
  18. </p>
  19. </form>
  20. </body>
  21. </html>

enctype=”multipart/form-data” 这个编码方式是啥 为神马要这样呢? 对请求头有何影响
上传成功后的请求头
image.png

使用es6的fetchAPI上传图片

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <p>
  10. <input type="text" name="a" />
  11. </p>
  12. <p>
  13. <input type="file" name="img" accept="image/*" multiple />
  14. </p>
  15. <p>
  16. <button>提交</button>
  17. </p>
  18. <img src="" alt="" />
  19. <script>
  20. function upload() {
  21. const inpA = document.querySelector("[name=a]");
  22. const inpFile = document.querySelector("[name=img]");
  23. const img = document.querySelector("img");
  24. const formData = new FormData(); //帮助你构建form-data格式的消息体
  25. formData.append("a", inpA.value);
  26. for (const file of inpFile.files) {
  27. formData.append("img", file, file.name);
  28. }
  29. fetch("/api/upload", {
  30. body: formData,
  31. method: "POST",
  32. })
  33. .then((resp) => resp.json())
  34. .then((resp) => {
  35. console.log(resp);
  36. if (resp.code) {
  37. //有错误
  38. alert(resp.msg);
  39. } else {
  40. img.src = resp.data;
  41. }
  42. });
  43. }
  44. document.querySelector("button").onclick = upload;
  45. </script>
  46. </body>
  47. </html>

image.png

enctype=”multipart/form-data” 这个编码方式是啥 对请求头有何影响

当使用postman发送上传图片的请求的code
image.png
你会发现——WebKitFormBoundary7MA4YWxkTrZu0gW这个动出现三次 这又是啥
先从

Content-Type

它是用来指示资源的MIME类型的

enctype=”multipart/form-data”

enctype是编码格式
multipart/form-data 是一种传输文件的格式如下图
image.png
image.png

boundary=——WebKitFormBoundary7MA4YWxkTrZu0gW

image.png
从这个图你就能看出来,最开始是以boundary=——WebKitFormBoundary7MA4YWxkTrZu0gW 开始的,而后面的数据也是
这不就是明显的分割符吗,而boundary的中文意思就是分割符,你再看图片,头部一次尾部一次,剩余的每个数据用这个分分割一次,
而boundary后面的字符知识随机生成出来的分割字符,这种格式很适合传输大数据。

上传的原理

上传不就是将文件读成二进制数据后编码发送给后端吗。说白就是body中的一段数据,其实get请求也能上传文件,实际上数据是发送过去的,只是服务器不认而已

express中实现文文件上传

需要使用的组件:multer
文档:https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md
剩余的自己看文档
示例:

  1. const express = require('express');
  2. const path = require('path');
  3. const multer = require('multer'); // 上传文件的中间件
  4. // 路由
  5. const router = express.Router();
  6. // 默认格式
  7. // const upload = multer({
  8. // dest: path.resolve(__dirname, '../public/img')
  9. // })
  10. const storage = multer.diskStorage({
  11. // 储存位置
  12. destination: function (req, file, cb) {
  13. cb(null, path.resolve(__dirname, '../public/img'));
  14. },
  15. // 文件名 默认是没有后缀名的
  16. filename: function (req, file, cb) {
  17. const ext = path.extname(file.originalname);
  18. const timeStamp = Date.now();
  19. const randomStr = Math.random().toString(36).slice(-6);
  20. const filename = `${timeStamp}${randomStr}${ext}`;
  21. cb(null, filename);
  22. },
  23. });
  24. const upload = multer({
  25. storage, // 磁盘存储引擎
  26. // 限制数据得大小
  27. limits: {
  28. fileSize: 1024 * 1024 * 3,
  29. },
  30. // 那些文件可以上传
  31. fileFilter: (req, file, cb) => {
  32. cb(null, true);
  33. const extname = file.originalname;
  34. const whitelist = ['.jpg', '.png', '.gif'];
  35. let istrue = false;
  36. whitelist.forEach((ele) => {
  37. if (extname.includes(ele)) {
  38. cb(null, true);
  39. istrue = true;
  40. } else {
  41. cb(null, false);
  42. }
  43. });
  44. if (!istrue) {
  45. cb(new Error(`your ext name of ${extname} is not support`));
  46. }
  47. },
  48. });
  49. // 单个数据
  50. router.post('/', upload.single('img'), (req, res) => {
  51. const url = `/upload/${req.file.filename}`;
  52. res.send({
  53. code: 0,
  54. msg: '',
  55. data: url,
  56. });
  57. });
  58. module.exports = router;

express.js

  1. const express = require('express');
  2. const app = express();
  3. app.use('/api/upload', require('./upload'))