文件上传,搞懂这8种场景就够了

本文详细介绍了文件上传的8种常见场景,包括单文件、多文件、目录、压缩目录、拖拽、剪贴板、大文件分块和服务端上传。每个场景都涉及不同的技术和实现细节,如前端的 formData、Koa 中间件处理,以及利用 JSZip、Clipboard API 等技术。通过本文,读者将理解各种文件上传方式的工作原理和实现方法。
摘要由CSDN通过智能技术生成

在日常工作中,文件上传是一个很常见的功能。在项目开发过程中,我们通常都会使用一些成熟的上传组件来实现对应的功能。一般来说,成熟的上传组件不仅会提供漂亮 UI 或好的交互体验,而且还会提供多种不同的上传方式,以满足不同的场景需求。

一般在我们工作中,主要会涉及到 8 种文件上传的场景,每一种场景背后都使用不同的技术,其中也有很多细节需要我们额外注意。今天阿宝哥就来带大家总结一下这 8 种场景,让大家能更好地理解成熟上传组件所提供的功能。阅读本文后,你将会了解以下的内容:

  • 单文件上传:利用 input 元素的 accept 属性限制上传文件的类型、利用 JS 检测文件的类型及使用 Koa 实现单文件上传的功能;

  • 多文件上传:利用 input 元素的 multiple 属性支持选择多文件及使用 Koa 实现多文件上传的功能;

  • 目录上传:利用 input 元素上的 webkitdirectory 属性支持目录上传的功能及使用 Koa 实现目录上传并按文件目录结构存放的功能;

  • 压缩目录上传:在目录上传的基础上,利用 JSZip 实现压缩目录上传的功能;

  • 拖拽上传:利用拖拽事件和 DataTransfer 对象实现拖拽上传的功能;

  • 剪贴板上传:利用剪贴板事件和 Clipboard API 实现剪贴板上传的功能;

  • 大文件分块上传:利用 Blob.sliceSparkMD5 和第三方库 async-pool 实现大文件并发上传的功能;

  • 服务端上传:利用第三方库 form-data 实现服务端文件流式上传的功能。

一、单文件上传

对于单文件上传的场景来说,最常见的是图片上传的场景,所以我们就以图片上传为例,先来介绍单文件上传的基本流程。

1.1 前端代码

html

在以下代码中,我们通过 input 元素的 accept 属性限制了上传文件的类型。这里使用 image/* 限制只能选择图片文件,当然你也可以设置特定的类型,比如 image/pngimage/png,image/jpeg

<input id="uploadFile" type="file" accept="image/*" />
<button id="submit" onclick="uploadFile()">上传文件</button>
复制代码

需要注意的是,虽然我们把 input 元素的 accept 属性设置为 image/png。但如果用户把 jpg/jpeg 格式的图片后缀名改为 .png,就可以成功绕过这个限制。要解决这个问题,我们可以通过读取文件中的二进制数据来识别正确的文件类型。

要查看图片对应的二进制数据,我们可以借助一些现成的编辑器,比如 Windows 平台下的 WinHex 或 macOS 平台下的 Synalyze It! Pro 十六进制编辑器。这里我们使用 Synalyze It! Pro 这个编辑器,来查看阿宝哥头像对应的二进制数据。

那么在前端能否不借助工具,读取文件的二进制数据呢?答案是可以的,这里阿宝哥就不展开介绍了。感兴趣的话,你可以阅读 JavaScript 如何检测文件的类型? 这篇文章。另外,需要注意的是 input 元素 accept 属性有存在兼容性问题。比如 IE 9 以下不支持,具体如下图所示:

(图片来源 —— caniuse.com/input-file-…

js

const uploadFileEle = document.querySelector("#uploadFile");

const request = axios.create({
  baseURL: "http://localhost:3000/upload",
  timeout: 60000, 
});

async function uploadFile() {
  if (!uploadFileEle.files.length) return;
  const file = uploadFileEle.files[0]; // 获取单个文件
  // 省略文件的校验过程,比如文件类型、大小校验
  upload({
    url: "/single",
    file,
  });
}

function upload({ url, file, fieldName = "file" }) {
  let formData = new FormData();
  formData.set(fieldName, file);
  request.post(url, formData, {
    // 监听上传进度
    onUploadProgress: function (progressEvent) {
      const percentCompleted = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total
      );
      console.log(percentCompleted);
     },
  });
}
复制代码

在以上代码中,我们先把读取的 File 对象封装成 FormData 对象,然后利用 Axios 实例的 post 方法实现文件上传的功能。 在上传前,通过设置请求配置对象的 onUploadProgress 属性,就可以获取文件的上传进度。

1.2 服务端代码

Koa 是一个简单易用的 Web 框架,它的特点是优雅、简洁、轻量、自由度高。所以我们选择它来搭建文件服务,并使用以下中间件来实现相应的功能:

const path = require("path");
const Koa = require("koa");
const serve = require("koa-static");
const cors = require("@koa/cors");
const multer = require("@koa/multer");
const Router = require("@koa/router");

const app = new Koa();
const router = new Router();
const PORT = 3000;
// 上传后资源的URL地址
const RESOURCE_URL = `http://localhost:${PORT}`;
// 存储上传文件的目录
const UPLOAD_DIR = path.join(__dirname, "/public/upload");

const storage = multer.diskStorage({
  destination: async function (req, file, cb) {
    // 设置文件的存储目录
    cb(null, UPLOAD_DIR);
  },
  filename: function (req, file, cb) {
    // 设置文件名
    cb(null, `${file.originalname}`);
  },
});

const multerUpload = multer({ storage });

router.get("/", async (ctx) => {
  ctx.body = "欢迎使用文件服务(by 阿宝哥)";
});

router.post(
  "/upload/single",
  async (ctx, next) => {
    try {
      await next();
      ctx.body = {
        code: 1,
        msg: "文件上传成功",
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值