10分钟学会文件上传

文件上传的核心就是 FileUpload 对象。在HTML文档中
<input type='file'>
每出现一次,一个FileUpload对象就会被创建。该对象包含的 value 属性保存了用户上传的文件名,并且该值是只读的,不可以被前端所修改的,当用户上传一个文件时,会触发 onchange 事件,可以以此当作钩子来操作。

在开始的时候,大家写 文件上传 功能的时候,会采用这种方法:

<form action='Upload.php' method='POST' enctype='multipart/form-data'>
    <input type='file' name='file'></input>
    <button type='submit'>提交</button>
</form>

但是这样的弊端就是上传后被刷新了!!!

现代前端都是基于Ajax进行文件上传的

还记得Ajax怎么写么?

var xml = new XMLHttpReques();
xml.open('POST', 'Upload.php');
xml.setRequestHeader('Content-Type', 'multipart/form-data');
xml.send(data);

xml.onchange = function(){
    if(xml.readyState === 4 && xml.status === 200){
        console.log('success');
    }else{
        console.log('fail');
    }
}

以上是用level1版本,现在level2版本了。
这个版本:
1,可以支持文件上传了,
2,提供了进度提示,
3,可以设置超时处理。

var xhr = new XMLHttpRequest();
var formData = new FormData();
var fileInput = $("input[type='file']");
var file = fileInput.files[0];
// 第一个参数是 属性名  第二个参数是 属性值
formData.append('myFile', file);
xhr.open('POST', 'Upload.php');

// 这个onload相当于level1中的 xml.readyState === 4
xhr.onload = function(){
    if(this.status === 200){
        console.log('success')
    }
}
xhr.send(formData);
xhr = null;

这样就可以通过ajax来无刷新上传文件了。

如果我们有对监听上传的进度的需求,那么需要拿到 upload 属性下面的 onprogress 方法。

onprogress 的事件回调方法中可以监听文件上传的进度,因为event下面有 loaded 和 total 属性, 前者是已上传,后者是文件总大小。 那么通过 event.loaded / event.total * 100 来拿到上传进度。

那么如何在前端展现出这个进度条呢?

HTML5为我们提供了一个 progress 标签。

<progress value='10' max='100'>
</progress>

这个标签是有默认样式的,如果想自定义样式,可参考 这篇文章

当然我们也可以自己通过div来模拟进度条效果,但是缺少语义化。

图片预览

文件上传另一个重要的需求是图片预览

常规的思路是,当前端把图片提交之后,再向服务器中请求图片,但是这恐怕不算是 预览 。
已经上传了,还怎么会叫预览呢?

好在HTML5中已经支持图片预览——FileReader。
对此不熟悉的童鞋可以访问 MDN

FileReader读取的是用户本机上的图片,而不是服务器上的。
因为FileReader读取是异步的,所以这里会有几个钩子

  • onabort 读取操作被终止
  • onerror 读取操作发生错误
  • onload 读取操作成功完成
  • onloaded 读取操作完成,但不一定是成功。 可能是 onerror 也可能是 onload
  • onprogress 读取操作的进度
function preview(){
    var previewArea = $('#previewArea');
    var img = docuemnt.createElement('img');
    var fileInput = $('#file');
    // 这里是假设只上传了一个图片
    var file = fileInput.file[0];
    previewArea.appendChild(img);

    var reader = new FileReader();
    // 这个是读取的
    reader.readAsDataURL(file);
    reader.onload = function(e){
        // 这里是把图片资源转化为base64格式了
        img.src = e.target.result;
    }
}

多文件支持

想让文件上传支持多文件功能, 只需:

<input type='file' multiple>

这样就可以选择多文件上传了,但是需要注意的是,我们之前的代码逻辑都是按照单文件的逻辑来写的

如果是多文件的话,我们就需要把files文件循环添加到formData.append()里面

var fileInput = document.getElementById("myFile");
var files = fileInput.files;
var formData = new FormData();

for(var i = 0; i < files.length; i++) {
    var file = files[i];
    formData.append('files[]', file, file.name);
}

拖拽

var dropArea;

dropArea = document.getElementById("dropArea");
dropArea.addEventListener("dragenter", handleDragenter, false);
dropArea.addEventListener("dragover", handleDragover, false);
dropArea.addEventListener("drop", handleDrop, false);

// 阻止dragenter和dragover的默认行为,这样才能使drop事件被触发
function handleDragenter(e) {
    e.stopPropagation();
    e.preventDefault();
}

function handleDragover(e) {
    e.stopPropagation();
    e.preventDefault();
}

function handleDrop(e) {
    e.stopPropagation();
    e.preventDefault();

    var dt = e.dataTransfer;
    var files = dt.files;

    // handle files ...
}

样式

另一个需求是更改文件上传的默认样式

我们可以通过

<a href='javascript:;' class='file'>选择文件
    <input type='file'>
</a>

然后通过设置 a 的样式来达到效果 但是点击的时候还是input的效果 所以我们直接阻止了
a 的默认效果 也可以通过 preventdefault 实现。

代码:

 .file {
     position: relative;
     display: inline-block;
     background: #fff;
     border: 1px solid #ccc;
     border-radius: 4px;
     overflow: hidden;
     color: #333;
     text-decoration: none;
     text-indent: 0;
 }
 .file input {
     position: absolute;
     font-size: 100px;
     right: 0;
     top: 0;
     opacity: 0;
 }
 .file:hover {
     background: #AADFFD;
     border-color: #78C3F3;
     color: #004974;
     text-decoration: none;
 }
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值