文件上传呢,肯定少不了先获得/读取文件,咱们一步一步往下看~
一种通过 File API 规范与本地文件交互的标准方式。
允许我们异步读取存储在用户计算机上的文件(或者原始数据缓冲区)的内容,可以监控读取进度、找出错误并确定加载何时完成。使用File
或Blob
对象指定要读取的文件或数据。
最简单的例子就是通过表单获取上传的文件信息啦~
<input id="input" type="file">
<script>
const input = document.querySelector('input[type=file]')
input.addEventListener('change', ()=>{
console.log(input.files);//返回一个数组,里面是上传的文件
}
script>
console.log(input.files)
输出内容~
戳此看更详细的解读
很显然,上面的文件信息并不能获取文件的内容。终于到了我们的FileReader
出场啦,它的功能是读取(解析)文件!
我们获取了 File引用后,实例化 FileReader 对象,以便将其内容读取到内存中。加载结束后,将触发读取程序的 onload
事件,而其 result
属性可用于访问文件数据。
FileReader包括四个异步读取文件的选项:
FileReader.readAsBinaryString(Blob|File)
- result属性将包含二进制字符串形式的 file/blob 数据。每个字节均由一个 [0…255] 范围内的整数表示。
FileReader.readAsText(Blob|File, opt_encoding)
- result属性将包含文本字符串形式的 file/blob 数据。该字符串在默认情况下采用“UTF-8”编码。使用可选编码参数可指定其他格式。
FileReader.readAsDataURL(Blob|File)
- result 属性将包含编码为数据网址的 file/blob 数据。
FileReader.readAsArrayBuffer(Blob|File)
- result属性将包含ArrayBuffer 对象形式的 file/blob 数据。
对FileReader 对象调用其中某一种读取方法后,可使用onloadstart
、onprogress
、onload
、onabort
、onerror
和 onloadend跟踪其进度。
废话不多说,直接上例子吧,看完就理顺了!
<input id="input" type="file">
<script>
const input = document.querySelector('input[type=file]')
input.addEventListener('change', ()=>{
const reader = new FileReader()
reader.readAsDataURL(input.files[0]) // input.files[0]为第一个文件
console.log(reader);//输出结果看下图~
reader.onload = ()=>{
const img = new Image()
img.src = reader.result;// reader.result为获取结果
document.body.appendChild(img)
}
}, false)
script>
有时候上传的文件非常的大,可能会导致上传速度非常慢,为了提高上传速度,所以就有了文件切片的思想,通过彼此独立的字节范围块读取和发送文件。然后,由服务器组件负责按正确顺序重建文件。
使用Blob.slice
方法来对文件进行分割,同时该方法在不同的浏览器使用方式不同。
兼容代码~
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
下面看具体代码实例~
<input type="file" id="files" name="file" />
Read bytes:
<span class="readBytesButtons">
<button data-startbyte="0" data-endbyte="4">1-5button>
<button data-startbyte="5" data-endbyte="14">6-15button>
<button data-startbyte="6" data-endbyte="7">7-8button>
<button>entire filebutton>
span>
<div id="byte_range">div>
<div id="byte_content">div>
<script>
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!'); return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
console.log(start)
document.getElementById('byte_range').textContent = ['Read bytes: ', start + 1, ' - ', stop + 1, ' of ', file.size, ' byte file'].join('');
}
};
const blobSlice =
File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
reader.readAsBinaryString(blobSlice.call(file,start,stop+1))
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
script>
使用异步事件处理时还能顺便获得一项优势,那就是能够监控文件的读取进度;这对于读取大文件、查找错误和预测读取完成时间非常实用。onloadstart
和 onprogress
事件可用于监控读取进度。
解决了大文件上传速度差的问题,如果很不幸,突然遇到网络中断了,已经上传的部分还得重新上传(害!),是可忍熟不可忍!!断点续传来助力!
具体就是——已上传的部分跳过,只传未上传的部分。
重新上传的时候使用spark-md5
来生成文件 hash,区分此文件是否已上传。
那就顺便补充一下spark-md5的知识吧~
一个前端类包,戳此下载
作用:无需上传文件就快速获取本地文件md5。
md5:每个文件的md5值都是唯一的,我们可以根据通过 SparkMD5
去给每个文件生成一个hash值,这有什么好处呢?
正因为每个文件的md5是一样的,那么,我们在做文件上传的时候,就只要在前端先获取要上传的文件md5,并把文件md5传到服务器,对比之前文件的md5,如果存在相同的md5,我们只要把文件的名字传到服务器关联之前的文件即可,并不需要再次去上传相同的文件,再去耗费存储资源、上传的时间、网络带宽,实现真正意义上的“秒传”!
下面来唠一下它怎么用?
(1)直接通过构造函数SparkMD5调用方法
var hexHash = SparkMD5.hash('Hi there');
//生成一个十六进制哈希 d9385462d3deff78c352ebb3f941ce12
var rawHash = SparkMD5.hash('Hi there', true);
//生成一个原始哈希(二进制数据) ÔŒÙ
(2)下面这种比较普遍~
var spark = new SparkMD5();
spark.append('Hi');
spark.append(' there');
var hexHash = spark.end(); // hex hash
var rawHash = spark.end(true); // raw hash(binary string)
console.log(hexHash);//十六进制哈希 d9385462d3deff78c352ebb3f941ce12
console.log(rawHash);//原始哈希(二进制数据) ÔŒÙ
ps:SparkMD5
还有很多其他的方法,详情请戳此,下面也会讲一些常用的~
demo(大文件上传+断点续传),有需要的小伙伴可以去看看我写的demo
ps:上传文件到服务器的话,一般是用FormData
对象,此时content-type就是multipart/form-data
,这个demo里面也有用到~
希望看到这里的你,已经懂啦!