File
1、作用:可以读取本地文件内容;
2、操作方式:通过<input type="file"> 或 通过拖拽来选择本地文件。
3、使用:
监听input的change 事件,在事件对象中的target里,有个files属性,值是一个类对象,里边装的就是文件的一些信息,分别是:
name:文件名称,只读字符串。
size:以字节数为单位的文件大小。
type:文件的MIME类型,只读字符串,档类型不确定时,为 ""。(相当于文件类型)
<input id="file" type="file">
<script>
let f = document.getElementById('file')
f.addEventListener('change', (e) => {
console.log(e.target.files[0])
})
</script>
4、多文件上传,在标签上添加 nultiple 属性即可
<input id="file" type="file" multiple>
封装上传文件,返回文件大小类型及名称
<input id="file" type="file" multiple>
<script>
function formatSize(bytes) {
const GB = Math.pow(1024, 4)
const M = Math.pow(1024, 2)
const KB = Math.pow(1024, 1)
if (bytes >= GB) {
return (bytes / GB).toFixed(2) + 'GB'
} else if (bytes >= M) {
return (bytes / M).toFixed(2) + 'M'
} else if (bytes >= KB) {
return (bytes / KB).toFixed(2) + 'KB'
}
}
let file = document.getElementById('file')
file.addEventListener('change', (e) => {
let arr = []
let len = e.target.files['length']
let files = e.target.files
for(let i = 0; i <len; i ++) {
let obj = {}
obj['size'] = formatSize(files[i]['size'])
obj['name'] = files[i]['name']
obj['type'] = files[i]['type']
arr.push(obj)
obj = {}
}
})
</script>
5、样式重写
相信大家已经看出来了,上传文件自带的样式非常丑陋,下边提供两种方式改写样式:
方式一:
思路:文件上传样式display:none; 点击别的元素,在处理函数中去触发文件上传的点击事件
<input id="file" type="file" style="display: none" onchange="handleFile(this.files)">
<button id="btn">上传文件</button>
<script>
let file = document.getElementById('file')
let btn = document.getElementById('btn')
// input 的onchange事件的处理函数
function handleFile(files) {
console.log('files', files)
}
// 点击按钮
btn.addEventListener('click', () => {
if (file) {
file.click() // 触发input的点击事件,从而会吊起文件上传
}
e.preventDefault() // 阻止默认事件
})
</script>
方式二:
不使用js(click方法)来唤起文件上传窗口,使用 <label> 元素.
可以为 label 添加 样式
<style>
#file{
position: absolute;!important;
height: 1px;
width: 1px;
overflow: hidden;
/* 裁剪一个【绝对定位】的元素, rect (top, right, bottom, left)*/
clip: rect(1px, 1px, 1px, 1px);
}
/* outline:thin dotted 替换其默认focus时的样式
*/
input#file:focus{
outline: thin dotted;
}
</style>
<input id="file" type="file" multiple>
<label for="file">上传文件</label>
<script>
let file = document.getElementById('file')
file.addEventListener('change', (e) => {
console.log('e', e)
})
</script>
拖拽上传:
思路:H5的拖动监听事件:
(1)drapenter - 当拖拽元素进入放置目标时触发。
(2)drapover - 当拖拽元素在放置目标中移动时触发,类似mouseover
(3)drap - 当拖拽元素放置在目标时触发(拖拽元素放置在目标元素之后,直接触发input的onchange事件,即可完成拖拽上传)
<div class="box">拖拽上传</div>
<input style="display: none;" type="file" id="file" onchange="handleFile">
<script>
let dropbox = document.getElementsByClassName('box')[0]
// 拖拽完成之后触发
function handleFile(e) {
console.log('file', e)
}
// 阻止默认事件 及 冒泡
function dragenter(e) {
e.stopPropagation()
e.preventDefault()
}
// 阻止默认事件 及 冒泡
function dragover(e) {
e.stopPropagation()
e.preventDefault()
}
// 元素放置目标元素时的处理函数,事件对象e中有一个dataTransfer对象,里边files字段
// 就是文件信息列表,再将它传给handleFiles()函数,在这之后跟文件点击上传一样了。
function drop(e) {
e.stopPropagation()
e.preventDefault()
let dt = e.dataTransfer
let files = dt.files
handleFile(files)
}
dropbox.addEventListener("dragenter", dragenter, false)
dropbox.addEventListener("dragover", dragover, false)
dropbox.addEventListener("drop", drop, false)
</script>
FileReader
1、定义:
FileReader 对象允许web应用程序异步的读取本地电脑上的文件,使用File或blob对象指定读取的文件或数据。
用大白话讲:fileReader可以读取指定文件的信息包含文件名、大小、类型、修改时间 等等 ,读取的意图用来传给后台、或者显示图片缩略图 等等· · ·
File对象: 指的是用户点击文件上传返回的 FileList 对象,或者 用户拖拽生成的 DataTransfer对象。
let fileRd = new FileReader()
console.log(fileRd)
2、属性 - 只读
(1) fileRd.error - 表示读取文件时发生的错误
(2) fileRd.readyState - 表示 fileRd状态的数字 ,如下:
0:换没有加载任何数据
1:数据正在被加载
2:已完成全部的读取请求
(3) fileRd.result - 文件的内容,该属性读取操作完成后才有效。
3、常用事件处理函数
fileRd.onabort - 处理abort事件,该事件在读取操作被中断时,触发。
fileRd.onload - 处理load事件,改时间在读取完成时触发。
4、方法
fileRd.abort( ) - 终止读取操作,再返回时,readyState属性为DONE
fileRd.readAsArrayBuffer( ) - 开始读取指定的Blob中的内容,一旦读取完成,result属性中将包含所读取文件的原始二进制数据。
fileRd.readAsDataURL( ) - 开始读取指定的Blob中的内容,一旦读取完成,result属性中将包含一个data:URL格式的Base64字符串,以表示读取的内容。
fileRd.readAsText( ) - 开始读取指定的Blob中的内容,一旦读取完成,result属性中将包含字符串,以表示所读取的文件内容。
看到这里,先来解释一波吧,之前没使用过的应该看晕了O(∩_∩)O哈哈~:
上边几个属性、处理函数、方法使用最多的是
fileRd.readAsDataURL( )读取一个文件对象(通常读取图片格式的较多,目的转base64),这个文件对象是用户点击文件上传之后,通过事件对象e获取的,上边有好多例子,不啰嗦了!读取完之后呢,会被fileRd.onload监听到,在onload事件处理函数的参数ProgressEvent对象中可以获取到读取的结果,来来,看个小例子:
<input type="file" id="file">
<script>
let file = document.getElementById('file')
// 监听文件上传
file.addEventListener('change', (e) => {
const files = e.target.files[0]
// new 一个文本文件读取的对象
let render = new FileReader()
// 监听读取完成的处理函数
render.onload = function(fileEvent) {
console.log('e', fileEvent) // 来来看下它的样子
console.log(fileEvent.target.result) // 这个就是读取的结果
}
// 把文件读取为base64格式
render.readAsDataURL(files)
})
</script>
先来看下上边 fileEvent 对象的样子:
在看看读取结果的样子:
之前做图片上传的朋友应该很熟悉,这个就是base64格式,可以直接赋值给img标签的scr属性:
好了说到这基本结束了,以后会及时更新以及加一些小案例。
再举个栗子吧,加深印象:
显示用户上传的图片缩略图:
看完上边说的这些,这个需求很简单:
<input type="file" id="file">
<div id="img-box"></div>
<div class="file-name"></div>
<div class="file-type"></div>
<div class="file-size"></div>
<script>
// size转KB、M、GB
function formatSize(bytes) {
const GB = Math.pow(1024, 4)
const M = Math.pow(1024, 2)
const KB = Math.pow(1024, 1)
if (bytes >= GB) {
return (bytes / GB).toFixed(2) + 'GB'
} else if (bytes >= M) {
return (bytes / M).toFixed(2) + 'M'
} else if (bytes >= KB) {
return (bytes / KB).toFixed(2) + 'KB'
}
}
let file = document.getElementById('file'),
imgBox = document.getElementById('img-box'),
fileType = document.getElementsByClassName('file-type')[0],
fileSize = document.getElementsByClassName('file-size')[0],
fileName = document.getElementsByClassName('file-name')[0];
// 监听文件上传
file.addEventListener('change', (e) => {
let img = new Image()
let files = e.target.files[0]
let render = new FileReader()
render.onload = (ev) => {
img.src = ev.target.result
imgBox.appendChild(img)
fileType.innerText = `图片类型: ${files['type']}`
fileSize.innerText = `图片大小: ${formatSize(files['size'])}`
fileName.innerText = `图片名字: ${files['name']}`
}
render.readAsDataURL(files)
})
</script>