您的位置:首页 > 其它

10分钟学会文件上传

2017-07-25 15:56 169 查看
文件上传的核心就是 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('s
4000
uccess')
}
}
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: