从前端实战角度聊聊Upload上传的那些坑与优化技巧

令狐娇娇 组件 阅读 574
赞 12 收藏
二维码
手机扫码查看
反馈

为啥要对比这几种上传方案?

最近项目里又碰到了文件上传的需求,说实话,这种需求我做过不少次了,但每次都有点小坑。这次想着干脆把常用的几种上传方案拿出来对比一下,顺便总结下自己的踩坑经验。主要涉及的是原生HTML的<input type=”file”>、第三方库(比如Dropzone.js)、以及基于前端框架(React/Vue)的实现。

从前端实战角度聊聊Upload上传的那些坑与优化技巧

我的结论是:看场景选方案。如果你需要快速上手且对功能要求不高,直接用原生HTML;如果想界面好看一点、用户体验好一些,Dropzone.js是个不错的选择;如果是大型项目,建议自己封装一个基于框架的组件。

谁更灵活?谁更省事?

先说最简单的原生HTML方案吧:

<input type="file" id="upload" />
<script>
  document.getElementById('upload').addEventListener('change', (event) => {
    const files = event.target.files;
    console.log(files);
  });
</script>

代码确实简单,基本没什么学习成本,适合那种临时需求或者小型项目。但问题是,它真的太丑了!默认样式基本上没法直接用在生产环境。而且功能也很有限,比如拖拽上传、图片预览这些常见需求就做不了。

然后是我比较喜欢用的Dropzone.js:

<form action="https://jztheme.com/upload" class="dropzone"></form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/dropzone.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/dropzone.min.css" />
<script>
  Dropzone.options.myAwesomeDropzone = {
    maxFilesize: 2, // MB
    acceptedFiles: 'image/*',
    init: function () {
      this.on('success', function (file, response) {
        console.log('File uploaded successfully:', response);
      });
    },
  };
</script>

这个库的好处就是开箱即用,UI也挺不错的,默认支持拖拽上传和文件类型限制。不过缺点也有,比如它的体积稍微大了一点(gzip后大概16KB),如果你的项目本身已经有很多依赖了,这点体积可能会影响加载速度。还有就是,定制化程度有限,有些特殊需求还得改源码。

最后是基于框架的自定义上传组件,拿React举个例子:

import React, { useState } from 'react';

function UploadComponent() {
  const [files, setFiles] = useState([]);

  const handleFileChange = (event) => {
    const selectedFiles = Array.from(event.target.files);
    setFiles(selectedFiles);
  };

  const uploadFiles = async () => {
    const formData = new FormData();
    files.forEach((file) => formData.append('files', file));

    try {
      const response = await fetch('https://jztheme.com/upload', {
        method: 'POST',
        body: formData,
      });
      const result = await response.json();
      console.log('Upload success:', result);
    } catch (error) {
      console.error('Upload failed:', error);
    }
  };

  return (
    <div>
      <input type="file" multiple onChange={handleFileChange} />
      <button onClick={uploadFiles}>Upload</button>
      <ul>
        {files.map((file, index) => (
          <li key={index}>{file.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default UploadComponent;

这个方案的优点就是完全可控,你可以随心所欲地扩展功能,比如加进度条、图片预览、错误提示等等。但我得承认,写起来确实麻烦一些,特别是对于初学者来说,光是搞懂FormData和异步操作就够折腾一阵子了。

性能对比:差距比我想象的大

从性能角度看,原生HTML当然是最快的,毕竟没任何额外依赖。而Dropzone.js因为引入了一个外部库,所以加载时间会稍长一点,尤其是网络条件不好的时候,可能会有点延迟。

至于React/Vue这类框架方案,性能其实更多取决于你的代码质量和优化水平。比如我之前在某个项目里用Vue写了个上传组件,刚开始没注意销毁事件监听器,结果内存占用越来越高,后来才发现问题出在onMounted和onUnmounted的生命周期管理上。

我的选型逻辑

总的来说,我会根据项目需求来选:

  • 简单需求:直接用原生HTML,速度快,也没必要引入额外依赖。
  • 中等复杂度需求:比如需要拖拽上传、图片预览,我会用Dropzone.js。虽然它的体积大了点,但开发效率高,省了不少事。
  • 高度定制化需求:比如需要实时显示上传进度、多文件并发上传,那肯定得自己封装组件了。

这里提醒一下,用Dropzone.js的时候要注意版本兼容性,我之前踩过一次坑,因为用了老版本,结果某些浏览器上根本没法触发change事件。

踩坑提醒:这三点一定注意

1. 文件大小限制:不管是哪种方案,服务器端一定要做好文件大小校验,前端只是辅助。我之前有个项目,前端写了限制2MB,结果用户通过浏览器调试工具绕过了这个限制,直接传了个几十MB的文件上来,差点把服务器搞崩。

2. 跨域问题:如果你的上传接口和前端页面不在同一个域名下,别忘了配置CORS。我曾经试过忘记配,导致上传一直报错,折腾了半天才发现是跨域的问题。

3. 图片预览的安全性:有些方案会直接用FileReader生成base64格式的图片预览,但如果用户上传的是恶意文件,可能会有安全风险。建议在展示前加上类型校验。

以上是我的对比总结

这篇文章主要是分享我在实际项目中的使用经验,不同人可能有不同的偏好。我个人觉得,技术选型没有绝对的好坏,关键还是看需求和场景。如果有更好的实现方式或者你觉得我的分析有问题,欢迎评论区交流!

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论