目录
概括
1. 基本概念
1.1 Blob:存储二进制文件的“容器”。不可变。
1.2 File:File接口基于Blob
1.3 ArrayBuffer :表示原始的二进制数据缓冲区
1.4 FileReader:异步文件读取,可进行文件类型转换
1.5 URL.createObjectURL():file转成url
1.6 new Image():生成一个尚未被插入 DOM 树中的 img标签
2. 基本功能
2.1 Blob、File可实现的功能
2.2 ArrayBuffer可实现的功能
2.3 Blob(File)和ArrayBuffer区别
-
除非你需要使用 ArrayBuffer 提供的写入/编辑的能力,否则 Blob 格式可能是最好的。
-
Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
-
ArrayBuffer 是存在内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
-
Blob 与 ArrayBuffer 对象之间是可以相互转化的:
- 使用 FileReader 的
readAsArrayBuffer()
方法,可以把 Blob 对象转换为 ArrayBuffer 对象; - 使用 Blob 构造函数,如
new Blob([new Uint8Array(data]);
,可以把 ArrayBuffer 对象转换为 Blob 对象。
- 使用 FileReader 的
2.4 FileReader可实现的功能
2.5 URL.createObjectURL()可实现的功能
URL.createObjectURL()也是生成URL。
其方法的参数是Blob对象/File对象。
其返回值格式是blob:
开头的地址。比如:blob:http://172.19.40.138:2023/eff2f372-3690-4862-8223-1a1e15150ae0
3. 小结(先看↓↓↓↓↓↓↓)
-
Blob(File)
、ArrayBuffer
都是文件“容器”。能用Blob就不用ArrayBuffer,除非需要写入/编辑的功能 -
FileReader
和URL.createObjectURL()
都可以将Blob(File)转为URL
。- 区别是URL的前缀不一样。
- 【FileReader】是
data:URL(Base64字符串)
。 - 【URL.createObjectURL()】是
blob:域名/...
。
- 【FileReader】是
- Data URL 和 Blob URL区别。
- 格式不同
- 长度不同,Data URL 中嵌入了资源内容,一般会很长。Blob URL 一般较短。
Blob URL 只能在当前应用内部使用
,把Blob URL复制到浏览器的地址栏中,是没法获取数据的。Data URL相比之下,就有很好的移植性,你能够在任意浏览器中使用。- 除了可以用作图片资源的网络地址,
Blob URL也可以用作其他资源的网络地址,例如html文件、json文件等
,为了保证浏览器能正确的解析Blob URL返回的文件类型,需要在创建Blob对象时指定相应的type。// 创建HTML文件的Blob URL var data = "<div style='color:red;'>This is a blob</div>"; var blob = new Blob([data], { type: 'text/html' }); var blobURL = URL.createObjectURL(blob); // 创建JSON文件的Blob URL var data = { "name": "abc" }; var blob = new Blob([JSON.stringify(data)], { type: 'application/json' }); var blobURL = URL.createObjectURL(blob);
- 区别是URL的前缀不一样。
-
new Image()
:生成一个尚未被插入 DOM 树中的 img标签
4. Vue前端下载文件,后端返回流的形式
4.1 axios.js请求封装:注意事项
// response响应拦截
instance.interceptors.response.use(
// 不能这样拦截,没法获取header,获取不到必要信息
// ({ data }) => {
// return data
// },
(res) => {
return res.data
},
(error) => {
return Promise.reject(error)
}
)
4.2 通过Blob直接下载
// 发送请求处理
// exportFile是请求,config里设置{ responseType: 'blob' }
exportFile(obj, { responseType: 'blob' }).then(res => {
console.log(res, '---res')
const data = res.data
const url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })) // 文件类型是xlsx
// 获取返响应头里的文件名,需要自己切割
let dis = res.headers['content-disposition']
let fileName = dis.split('attachment;filename=')[1]
// 如果fileName中包含 中文
fileName = decodeURIComponent(fileName)
// 通过a标签下载
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName||'excel.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
注意:
res.headers[‘content-disposition’]
,其值是如下类型字符串attachment;filename=xxx.xlsx
,需要自己切分。- 如果文件名是中文,则需要后端配合转码,后端在发送文件时,要将文件名进行java.net.URLEncoder.encode(fileName, “UTF8”) 转码,否则前端接收到的 res.headers[‘content-disposition’] 的中文信息是乱码的。后端转码后,前端通过
decodeURIComponent 解码
即可
- 在后台这样处理 :
String msg = URLEncoder.encode("中文", "UTF-8").replace("+","%20")
- 在前台这样处理:
decodeURIComponent(msg)
- 如果获取不到
headers['content-disposition']
的话,需要后端对该接口配置一下Header
- 在controller层中的二进制流文件下载方法下配置放行属性
response.setHeader("Access-Control-Expose-Headers", "content-disposition");
4.2.1 new Blob() 不同文件类型的 type 值
const url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }))
其中的type
值可以根据不同的文件类型进行设置。详情可以通过以下链接参考:
4.3 通过Blob+FileReader的方式下载
const blob = res
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function (ev) {
if (window.navigator.msSaveOrOpenBlob) {
// 兼容ie11
const blobObject = new Blob([blob])
window.navigator.msSaveOrOpenBlob(blobObject, '文件名称.xlsx')
} else {
const url = URL.createObjectURL(new Blob([blob]))
const a = document.createElement('a')
document.body.appendChild(a) // 此处增加了将创建的添加到body当中
a.href = url
a.download = '文件名称名称.xlsx'
a.target = '_blank'
a.click()
a.remove() // 将a标签移除
}
}
一、Blob对象
Blob(binary large object),二进制类文件大对象,是一个可以存储二进制文件的“容器”,HTML5中的Blob对象除了存放二进制数据外还可以设置这个数据的MIME类型。
注:File接口基于Blob
,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
1. Blob构造函数
new Blob([data], {type: "application/octet-binary"})
Blob构造函数接受两个参数,
- 第一个参数是一个包含实际数据的数组,
- 第二个参数是数据的MIME类型。
2. Blob属性
2.1 Blob.size
- blob对象的数据大小
2.2 Blob.type
- 表示blob对象所包含数据的MIME类型。如果实例化时未指明类型,则该值为空字符串。
3. Blob方法
3.1 Blob.slice()
- 相当于数组Array.slice方法,表示截取指定范围的数据,形成新的blob对象。(用于文件的分割上传)
3.2 Blob.arrayBuffer()
- 返回一个 Promise 对象且包含 blob 所有内容的二进制格式的 ArrayBuffer。
(Blob转成ArrayBuffer)
二、File对象
1. 前言
File指本地文件系统中的文件。File对象提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
File是一个具有名字同时可能也有一个修改日期的Blob。
获取方式:
可以从一个由 <input type="file"/>
元素组成的 files 数组中获取,或者从一个由与 drop 事件的 Event 对象关联的 DataTransfer 对象组成的 files 数组中,取得一个用户选择的文件。
2. 构造函数
var myFile = new File(bits, name[, options]);
返回一个新构建的文件对象(File)。
参数:
- bits:
ArrayBuffer
,ArrayBufferView
,Blob
,或者DOMString对象的 Array
— 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。 - name:USVString,表示文件名称,或者文件路径。
- options: 可选。配置属性。可用的选项如下:
- type: 表示将要放到文件中的内容的 MIME 类型。默认值为 “” 。
- lastModified: 表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()。
示例:
var file = new File(["foo"], "foo.txt", {
type: "text/plain",
});
3. 属性
file.lastModified
当前文件最后的修改时间,自 UNIX 时间起始值(1970年1月1日 00:00:00 UTC)以来的毫秒数。
file.name
当前文件的文件名(不包括路径)。
file.size
文件的大小。
file.type
文件的 MIME Type。
三、FileReader
1. 前言
FileReader是一种异步文件读取机制,结合input:file可以很方便的读取本地文件。
2. 构造函数
new FileReader()
2.1 构造函数的属性
属性 | 描述 |
---|---|
error (只读) | 一个DOMException(异常),表示在读取文件时发生的错误 。 |
readyState (只读) | 表示FileReader状态的数字,取值如下表。 |
★result (只读) | 文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。 |
(1)readyState
状态的属性
常量名 | 值 | 描述 |
---|---|---|
EMPTY | 0 | 还没有加载任何数据。 |
LOADING | 1 | 数据正在被加载。 |
DONE | 2 | 已完成全部的读取请求。 |
3. 方法
方法 | 描述 |
---|---|
abort():void | 中止读取操作。在返回时,readyState属性为DONE |
readAsArrayBuffer(file):void | 读取文件后,result 属性中保存的是被读取文件的 ArrayBuffer 数据对象。 |
readAsBinaryString(file):void | 读取文件后,result属性中包含所读取文件的原始二进制数据。 |
★readAsDataURL(file):void | 读取文件后,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。 |
★readAsText(file):void | 读取文件后,result属性中将包含一个字符串以表示所读取的文件内容。 |
4. 事件
事件名称 | 描述 |
---|---|
onabort | 当读取操作被中止时调用 |
onerror | 当读取操作发生错误时调用 |
★onload | 当读取操作成功完成时调用 |
onloadend | 当读取操作完成时调用,不管是成功还是失败 |
onloadstart | 当读取操作将要开始之前调用 |
onprogress | 在读取数据过程中周期性调用 |
注意:文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。
5. 基础案例
5.1 读取txt文件
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
this.fileList = [...this.fileList, file]
console.log(file, '上传的文件')
const reader = new FileReader()
reader.readAsText(file, 'utf8') // file文件
reader.onload = (e) => {
console.log(e, '读取文件成功的e')
const data = e.target.result
this.$refs.div.innerHTML += data // reader.result和e.target.result是一个东西
// this.$refs.div.innerHTML += reader.result // reader.result为获取结果
}
return false
}
}
}
</script>
<style lang="less"></style>
5.2 读取Excel文件(结合xlsx.js使用)
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
import XLSX from 'xlsx'
export default {
data () {
return {
fileList: []
}
},
methods: {
file2Xce (file) {
return new Promise(function (resolve, reject) {
const reader = new FileReader()
// 读取为二进制字符串
reader.readAsBinaryString(file)
reader.onload = function (e) {
const data = e.target.result
// XLSX.read解析数据,按照type 的类型解析
this.wb = XLSX.read(data, {
type: 'binary' // 二进制
})
console.log(this.wb, '---->解析后的数据')
const result = []
// 工作表名称的有序列表
console.log(this.wb.SheetNames, '---->工作表名称数组')
this.wb.SheetNames.forEach(sheetName => {
result.push({
// 工作表名称
sheetName: sheetName,
// 包含表数据的 数组(数据导出)
sheet: XLSX.utils.sheet_to_json(this.wb.Sheets[sheetName]) // this.wb.Sheets[sheetName]单工作表文件的第一个工作表
})
})
console.log(result, '----->表数据的数组')
resolve(result)
}
})
},
beforeUpload (file) {
this.fileList = [...this.fileList, file]
console.log(file, '上传的文件')
console.log(file.raw)
this.file2Xce(file).then((res) => {
console.log(res, 'resolve结果')
console.log('可以继续对res数据进行二次处理')
// 整理数据格式,只保留x和y
// if (xyToFormat(res)) {
// this.resList = xyToFormat(res)
// this.$emit('excelBeforeUploadEmit', file, this.resList)
// } else {
// this.resList = []
// }
})
return false
}
}
}
</script>
<style lang="less"></style>
5.3 读取图片文件(也可以实现图片预览)
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
this.fileList = [...this.fileList, file]
console.log(file, '上传的文件')
const reader = new FileReader()
reader.readAsDataURL(file) // 读取图片
reader.onload = (e) => {
console.log(e, '读取文件成功的e')
const img = new Image()
img.src = reader.result
console.log(reader.result, '----->data: URL 格式的 Base64 字符串')
this.$refs.div.appendChild(img)
}
return false
}
}
}
</script>
<style lang="less"></style>
四、URL(常用–>URL.createObjectURL())
1. 前言
一般使用window.URL.createObjectURL()
方法比较多,主要用于获取文件对应的url。
注:加不加window.一般情况下没区别.
如果浏览器尚不支持URL()构造函数,则可以使用Window中的Window.URL (en-US)属性。
2. 构造函数
new URL()
2.1 构造函数的属性
属性 | 描述 |
---|---|
hash | 从#开始往后的所有信息 |
host | 域名+端口 |
hostname | 域名 |
href | 完整 URL |
pathname | 端口之后,以 ‘/’ 起头,#之前的文件路径 |
search | 指示 URL 的参数字符串; 如果提供了任何参数,则此字符串包括所有参数,并以开头的“?”开头 字符。 |
3. 方法
方法 | 描述 |
---|---|
toString() | 返回包含整个 URL字符串,它是URL.href的同义词,尽管它不能用于修改值。 |
toJSON() | 返回包含整个 URL 的字符串。 它返回与href属性相同的字符串。 |
3.1 静态方法
方法 | 描述 |
---|---|
createObjectURL() | 返回一个字符串,包含一个唯一的 blob 链接(该链接协议为以 blob:,后跟唯一标识浏览器中的对象的掩码)方法参数:File对象和Blob对象 |
revokeObjectURL() | 销毁之前使用URL.createObjectURL()方法创建的 URL 实例。 |
4. 基础案例
4.1 基本demo打印url对象属性
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
// 属性
// 当前窗口的url:http://192.168.31.162:48079/historycity/#/test?pic=1
const url = new URL(window.location.href) // window.location.href当前窗口的url
console.log(url) // url对象
console.log(url.hash) // #/test?pic=1
console.log(url.host) // 192.168.31.162:48079
console.log(url.hostname) // 192.168.31.162
console.log(url.href) // http://192.168.31.162:48079/historycity/#/test?pic=1
console.log(url.pathname) // /historycity/
console.log(url.search)
console.log(url.searchParams)
console.log(url.toString()) // /historycity/
console.log(url.toJSON()) // /historycity/
return false
}
}
}
</script>
<style lang="less"></style>
4.2 实现图片预览
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
this.fileList = [...this.fileList, file]
const fileurl = window.URL.createObjectURL(file)
console.log(fileurl) // blob:http://192.168.31.162:48079/b7af9406-fad8-4f05-8b7c-32c10a3fef58
const img = new Image()
img.src = fileurl
this.$refs.div.appendChild(img)
return false
}
}
}
</script>
<style lang="less"></style>
五、HTMLImageElement(new Image())
1. 前言
一般用new Image(width,height)生成<img/>标签,结合图片预览使用
2. 构造函数
new Image([width,height])
创建了一个尚未被插入 DOM 树中的 HTMLImageElement 实例。
3. 属性
属性 | 描述 |
---|---|
alt | 表明图像的后备描述内容,会在图像无法加载时显示 |
src | 包含图像的完整的 URL,包含图像的基础 URL |
4. 方法
方法 | 描述 |
---|---|
decode() | 返回一个当图片解码后可安全用于附加到 DOM 上时 resolves 的 Promise 对象。 |
5.基础案例
5.1结合图片预览使用
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
this.fileList = [...this.fileList, file]
const fileurl = window.URL.createObjectURL(file)
console.log(fileurl) // blob:http://192.168.31.162:48079/b7af9406-fad8-4f05-8b7c-32c10a3fef58
const img = new Image()
img.src = fileurl
this.$refs.div.appendChild(img)
return false
}
}
}
</script>
<style lang="less"></style>
5.2 decode()的使用(使用场景:加载大图片时替换)
一个 decode() 的潜在用例:当在加载一个非常大的图片时(例如,一个在线相册),你可以在加载初期提供一个低分辨率的缩略图,之后通过实例化一个 HTMLImageElement 将该图像替换为一个全分辨率图像,设置其 source 为全分辨率图像 URL,使用 decode() 获取一旦全分辨率图像准备好被使用时 resolved 的 promise 对象。这时你可以使用当前可用的全分辨率图像替换之前的低分辨率图像。
<template>
<div class="emqrcode">
<a-upload :file-list="fileList" :before-upload="beforeUpload">
<a-button> <a-icon type="upload" /> Select File </a-button>
</a-upload>
<div>------------------------------</div>
<div ref="div"></div>
</div>
</template>
<script>
export default {
data () {
return {
fileList: []
}
},
methods: {
beforeUpload (file) {
this.fileList = [...this.fileList, file]
const fileurl = window.URL.createObjectURL(file)
const img = new Image()
img.src = fileurl
img.decode()
.then(() => {
this.$refs.div.appendChild(img)
})
.catch((encodingError) => {
// Do something with the error.
})
return false
}
}
}
</script>
<style lang="less"></style>