File对象
最常见的功能就是头像上传,文件预览,文件上传这些类似的功能
input上的type='file',就可以实现选择文件功能
先看一个示例
<div class="div-a">
<input type="file" id="file" class="div-input">
<div class="div-b" id="upfile"></div>
</div>
<input type="button" value="上传" id="btn">
<script>
let divB=document.getElementById('upfile'),
fileS=document.getElementById('file'),
btn=document.getElementById('btn');
let a=undefined;
fileS.addEventListener('change',function (params) {
// console.log(params.target.files);
a=params.target.files; //params.target.files获得的是一个类数组flieList对象,有length属性
})
btn.addEventListener('click',function(params){
if(a===undefined){
console.log('尚未选择文件');
}
else{
//异步上传文件
//console.log(a[0]);
let fd=new FormData();
fd.append('file',a[0], a[0].name);
let xhr=new XMLHttpRequest();
xhr.open('POST','服务器地址');
xhr.send()
}
})
</script>
其中a[0]获得的就是类似于:File(2554) {name: "changelog.txt", lastModified: 1477137622000, lastModifiedDate: Sat Oct 22 2016 20:00:22 GMT+0800 (中国标准时间), webkitRelativePath: "", size: 2554, …}
这边就是定了一个input为file,但是实际开发中不会直接使用这种样式,因此这边简单的修饰了一下,将file因此,在file的下面叠加了一个样式div,选择文件后将目标文件的files属性赋值给a,点击上传后将a上传至服务器
File对象的属性(只读)
属性 | 说明 |
lastModified | 文件的最近修改时间,从1970年开始的间隔时间 |
lastModifiedDate | 文件的最近修改日期,已经不推荐使用 |
name | 文件名 |
webkitRelativePath | 相对于用户所选择的文件夹路径 |
size | 文件大小,单位是字节 |
type | 文件的MIME类型,比如Image/jpeg |
Flie对象的方法
File对象本身没有任何方法,但是Flie对象继承自Blob,Blob有一个方法
Blob.slice([start[,end[,contentType]]])
和File结合使用的对象
FlileList
FileList,可以通过input元素的files属性获得,或者通过Drag和Drop API获取用户拖入到网页中的文件列表
<input type='file' id='file' multiple>
加了multiple属性后,用户就可以加入多个文件,这时候的FlieList就是一个类数组的形式,从下标0开始
属性/方法
属性/方法 | 说明 |
length | 包含的文件个数,只读 |
item() | 根据索引参数,返回对应的文件 |
Drag和Drop,拖拽事件
名称 | 作用 |
---|---|
dragstart | 在拖动时触发 |
dragend | 在拖动完成时触发 |
dragenter | 目标元素上绑定dragenter事件,当拖拽元素进入目标元素时触发 |
dragover | 目标元素上绑定dragover事件, 当拖拽元素在目标元素上移动时触发 |
drop | 目标元素上绑定drop事件, 并同时取消当前目标元素的dragover的默认事件, 当拖拽元素在目标元素上同时鼠标放开时触发事件.例: box为目标元素. box.addEventListener('dragover', function(e){console.log('dragover'); e.preventDefault();}); box.addEventListener('drop', function(e){console.log('drop');}); drop与dragend同时绑定时drop事件先触发 |
let drop = document.querySelector('.drop');
drop.addEventListener('dragover',function (params) { /*拖动到目标上方的事件*/
params.preventDefault(); /*不要执行与事件关联的默认动作*/
drop.classList.add('over')
});
drop.addEventListener('drop',function (params) { /*拖动到目标位置且松开触发*/
params.preventDefault();
drop.classList.remove('over');
console.log(params.dataTransfer.files); // 输出了一个fileList
})
FileReader
用来读取文件内容,读取过程是异步的,文件就是FileList的属性值
属性(都是只读)
属性 | 说明 |
error | 读文件异常时的错误信息 |
readyState | FileReader的状态,数值 |
result | 文件内容 |
当中关于readyState的取值
属性 | 值 | 说明 |
FlileReader.EMPTY | 0 | 尚未加载数据 |
FlieReader.LOADING | 1 | 正在加载数据 |
FileReader.DONE | 2 | 读取请求已完成 |
对象的方法
属性 | 说明 |
abort | 终止读取文件 |
readAsArrayBuffer | 读取的文件内容以ArrayBuffer的形式返回 |
readAsDataURL | 读取的文件以data:URL的形式返回 |
readAsText | 读取的文件内容以纯文本的形式返回 |
readAsBinaryString(非标准) | 读取的文件内容以原始二进制文本的形式返回 |
对象的事件(也就是可监听的事件)
事件 | 说明 |
onabort | 终止读取文件时触发 |
onerror | 读取异常时触发 |
onload | 去读成功时触发 |
onloadstart | 开始读取时触发 |
onloadend | 读取完成(可能成功,也可能失败)时触发 |
onprogress | 读取过程中触发 |
Blob
Blob,二进制大对象,是binary large object 的缩写,是用来存储类似文件的原始数据。
Blob构造函数
var aBlob=new Blob(array[,options])
- array:数组
- option:目前纳入规范的只有一个type,也就是类型
例如
var af=['<a id="a"><div id="b"></div></a>']
var aBlob=new Blob(af,{type:'text/html'})
方法
silce([start [,end [,contentType]]]):可以切割文件内容,
- start:起始索引
- end:结束索引
- contentType:指定类型
返回值也是一个blob对象,可以使用这个将大文件分割成多个小文件上传,如果上传中断,下次上传使用相同的方法,可以继续上传,但是前段页面一般不用大文件上传,有很多局限
URL
可以用来创建URL对象,也可以用来创建文件对象的临时地址,供用户或开发者使用,比如本地图片预览等
let url=new URL(urlStr,[base])
- urlStr:url字符串
- base:如果urlStr是一个相对地址,那么可以指定它的相对目标地址
示例
var url=new URL('../a','http://www.example.com/dogs')
console.log(url.hostname); //www.example.com
console.log(url.pathname); // /a
方法
方法 | 说明 |
URL.createObjectURL() | 创建对象在浏览器中的临时访问地址 |
URL.revokeObjectURL() | 回收使用createObjectURL方法创建的临时访问地址 |
createObjectURL(object)
接收的是一个参数,最常见的是flle或者Blob,返回的是一个可以在浏览器中访问的地址,这个地址的生命周期是当前窗口,窗口关闭或者刷新就无效了
revokeObjectURL(url)
参数就是创建的url地址,将其回收,节省浏览器的资源
示例:
var obURL=URL.createObjectURL(object);
URL.revokeObjectURL(obURL)
实际案例
限制文件的类型
<input type="file" id="file" class="div-input" accept="image/*">
只要将input中的设置accept属性,就可以限制文件类型(image/*是限制图片类型),accpet接收的是mime类型,多个值以逗号分隔,比如“image/png,image/jpeg”,也可以写文件的后缀名“.png,.jpeg”,也支持通配符*,比如“image/*”
限制文件大小,数量
<input type="file" id="file" class="div-input" accept="image/*" multiple>
只要拿到对象的fileList就可以判断数量和大小
<div class="div-a">
<input type="file" id="file" class="div-input" accept="image/*" multiple>
<div class="div-b" id="upfile"></div>
</div>
<input type="button" value="上传" id="btn">
<script>
let divB=document.getElementById('upfile')
fileS.addEventListener('change',function (params) {
if(a.length>3){
console.log('超出上限了');
fileS.value='';
return
}
let exceedSizeFiles=[].slice.call(a).filter(file=>{
return file.size > 10*1024;
})
if(exceedSizeFiles.length){
console.log("文件最大为10KB");
}
})
</script>
文件按钮美化
一种方法是将input隐藏,点击btn时,去关联点击input
<div class="div-a">
<input type="file" id="file" class="div-input" accept="image/*" multiple>
<div class="div-b" id="upfile"></div>
</div>
<input type="button" value="上传" id="btn">
<script>
let divB=document.getElementById('upfile'),
fileS=document.getElementById('file'),
btn=document.getElementById('btn');
fileS.addEventListener('change',function (params) {
})
btn.addEventListener('click',function(params){
fileS.click();
})
</script>
另外一种是使用label,通过label的for去关联input
<div class="div-a">
<label for="file">点击</label>
<input type="file" id="file" class="div-input" accept="image/*" multiple>
</div>
<input type="button" value="上传" id="btn">
<script>
let divB=document.getElementById('upfile'),
fileS=document.getElementById('file');
fileS.addEventListener('change',function (params) {
})
</script>
label的这种方法可以大大减少关联代码
将文本内容显示到网页上
<div class="div-a">
<label for="file">点击</label>
<input type="file" id="file" class="div-input" accept=".txt" >
</div>
<div id="text"></div>
<script>
let divB=document.getElementById('text'),
fileS=document.getElementById('file');
fileS.addEventListener('change',function (params) {
var a=new ReadFile();
a.read(params.target.files[0]);
})
function ReadFile(){
//this.file=file
}
ReadFile.prototype={
constructor:ReadFile,
read:function(file) {
let fr=new FileReader();
fr.onload=function(e){
document.querySelector('#text').innerHTML = e.target.result;
}
fr.readAsText(file)
}
}
</script>
将页面上的文本创建文本文件并下载
<textarea id="textbox">此处输入文本内容</textarea>
<input type="button" id="create" value="创建文本">
<a download="info.txt" id="downloadlink" style='display: none'>下载</a>
<script>
let textFile = null;
let makeTextFile=function(text){
let data= new Blob([text],{type:'text/plain'});
if(textFile !== null){
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
}
let create = document.getElementById("create");
let textbox = document.getElementById('textbox');
create.addEventListener('click',function (){
let fileUrl = makeTextFile(textbox.value);
let link = document.getElementById('downloadlink');
link.href = fileUrl;
link.click();
})
</script>
本地图片预览:FileReader.readAsDataURL
<input type="file" id="file" accept="image/*">
<script>
let fileInput = document.querySelector('#file');
fileInput.addEventListener('change',e=>{
showImage(e.target.files[0])
})
function showImage(image) {
let fr = new FileReader();
fr.onload= function (params) {
let img = new Image();
img.src = params.target.result;
document.body.appendChild(img)
}
fr.readAsDataURL(image);
}
</script>