原生js实现文件上传并显示进度条

6,766 阅读2分钟

背景

大部分web端业务系统都需要一个导入Excel功能,我们需要实现文件的上传,如果加上进度条,可以提升用户体验

效果图如下:

需要实现的功能点:

  • 选择文件上传、支持拖拽文件
  • 显示上传进度条

文件上传

使用<input type='file' onchange='changeFile'>

文件预览:读取文件名称、大小,使用onchange事件

 function changeFile(){
     var file = event.target.files[0];
 }
 

使用ajax异步上传,提交表单形式,使用H5的FormData对象

var form = new FormData();
form.append('name', 'xiaoqiu');
form.append('fileObj', file);

ajax提交文件

var xhr = new XMLHttpRequest();
xhr.open("post", 'http://localhost:5000/api/npoi/import', true);
xhr.send(form);     //提交表单数据

//文件传至服务器完成事件
xhr.onload = function () {
    alert("上传完成!");
};

//监听上传进度事件
xhr.upload.addEventListener('progress', handleProgress)

//上传进度监听处理
function handleProgress(e) {
    var progressBar = document.getElementById("progressBar");
    if (e.lengthComputable) {
        progressBar.max = e.total;
        progressBar.value = e.loaded;
    }
}

进度条使用的是H5提供的progress元素

 <progress id="progressBar" value="0" max="100"></progress>

div实现拖拽上传,依赖的事件:

  • ondrop
  • ondragover
  • ondragleave
function dropFile(e) {
    event.stopPropagation();
    event.preventDefault();
    var files = event.dataTransfer.files; // FileList object.
    console.log(files);
}

function dragOver(e) {
    event.stopPropagation();
    event.preventDefault();
    isDragOver = true;
}

function dragLeave(e) {
    event.stopPropagation();
    event.preventDefault();
    isDragOver = false;
}

html代码:
```html
<div class="upload-file-panel">
  <div class='upload-title'>【商品清单】导入:<a href='#'>点击此处下载模版</a></div>
  <div class="upload-panel-body" onclick="clickSelFile()" ondrop="dropFile()" ondragover="dragOver()" ondragleave="dragLeave()">
      <i class='fa fa-cloud-upload blue' style='font-size:2.5em;'></i>
      <input type="file" id="file" name="file" onchange="changeFile()" hidden="hidden">
      <div style="color:#9b9b9b;">选择或拖拽文件自动上传,仅支持Excel文件</div>
      <progress id="progressBar" value="0" max="100"></progress>
  </div>
  <div class='filename'>文件名:<span style='color:#ff8800'>test.xlsx</span><span class='blue' style='float:right' title='文件大小' id='upload-fileSize'>123kb</span></div>
  <div>
      文件更新时间:<span class='green'>2019-04-04 17:28:00</span>
      <span class='badge-rim bg-orange' style='float:right'>运行中</span>
  </div>
  <div class='upload-panel-notice'>
      正在上传...
  </div>
</div>

最后,你也可以封装成一个Vue组件使用

<uploader file-title="商品清单"
          :visible.sync="showUploder"
          upload-url="http://localhost:8080/api/v1/product/import"
          hub-url="http://localhost:8080/chathub"
          template-url="../../templates/商品导入模板.xlsx"
          @before-upload="formDataInit"
          @on-close="closeUploader">
</uploader>

注:如上的Excel业务数据处理进度需要借助websocket通信实现,后文会进行补充