除非你需要使用 ArrayBuffer 提供的写入/编辑的能力,否则 Blob 格式可能是最好的。
Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
ArrayBuffer 是存在内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
Blob 与 ArrayBuffer 对象之间是可以相互转化的:
readAsArrayBuffer()
方法,可以把 Blob 对象转换为 ArrayBuffer 对象;new Blob([new Uint8Array(data]);
,可以把 ArrayBuffer 对象转换为 Blob 对象。URL.createObjectURL()也是生成URL。
其方法的参数是Blob对象/File对象。
其返回值格式是blob:
开头的地址。比如:blob:http://172.19.40.138:2023/eff2f372-3690-4862-8223-1a1e15150ae0
Blob(File)
、ArrayBuffer
都是文件“容器”。能用Blob就不用ArrayBuffer,除非需要写入/编辑的功能
FileReader
和URL.createObjectURL()
都可以将Blob(File)转为URL
。
data:URL(Base64字符串)
。blob:域名/...
。Blob URL 只能在当前应用内部使用
,把Blob URL复制到浏览器的地址栏中,是没法获取数据的。Data URL相比之下,就有很好的移植性,你能够在任意浏览器中使用。Blob URL也可以用作其他资源的网络地址,例如html文件、json文件等
,为了保证浏览器能正确的解析Blob URL返回的文件类型,需要在创建Blob对象时指定相应的type。// 创建HTML文件的Blob URL
var data = "This is a blob";
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);
new Image()
:生成一个尚未被插入 DOM 树中的 img标签
// response响应拦截
instance.interceptors.response.use(
// 不能这样拦截,没法获取header,获取不到必要信息
// ({ data }) => {
// return data
// },
(res) => {
return res.data
},
(error) => {
return Promise.reject(error)
}
)
// 发送请求处理
// 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");
const url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }))
其中的type
值可以根据不同的文件类型进行设置。详情可以通过以下链接参考:
https://blog.csdn.net/L_yupeng/article/details/128242933
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(binary large object),二进制类文件大对象,是一个可以存储二进制文件的“容器”,HTML5中的Blob对象除了存放二进制数据外还可以设置这个数据的MIME类型。
注:File接口基于Blob
,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
new Blob([data], {type: "application/octet-binary"})
Blob构造函数接受两个参数,
(Blob转成ArrayBuffer)
File指本地文件系统中的文件。File对象提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
File是一个具有名字同时可能也有一个修改日期的Blob。
获取方式:
可以从一个由
元素组成的 files 数组中获取,或者从一个由与 drop 事件的 Event 对象关联的 DataTransfer 对象组成的 files 数组中,取得一个用户选择的文件。
var myFile = new File(bits, name[, options]);
返回一个新构建的文件对象(File)。
参数:
ArrayBuffer
,ArrayBufferView
,Blob
,或者 DOMString对象的 Array
— 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。示例:
var file = new File(["foo"], "foo.txt", {
type: "text/plain",
});
file.lastModified
当前文件最后的修改时间,自 UNIX 时间起始值(1970年1月1日 00:00:00 UTC)以来的毫秒数。
file.name
当前文件的文件名(不包括路径)。
file.size
文件的大小。
file.type
文件的 MIME Type。
FileReader是一种异步文件读取机制,结合input:file可以很方便的读取本地文件。
new FileReader()
属性 | 描述 |
---|---|
error (只读) |
一个DOMException(异常),表示在读取文件时发生的错误 。 |
readyState (只读) |
表示FileReader状态的数字,取值如下表。 |
★result (只读) |
文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。 |
readyState
状态的属性常量名 | 值 | 描述 |
---|---|---|
EMPTY |
0 | 还没有加载任何数据。 |
LOADING |
1 | 数据正在被加载。 |
DONE |
2 | 已完成全部的读取请求。 |
方法 | 描述 |
---|---|
abort():void |
中止读取操作。在返回时,readyState属性为DONE |
readAsArrayBuffer(file):void |
读取文件后,result 属性中保存的是被读取文件的 ArrayBuffer 数据对象。 |
readAsBinaryString(file):void |
读取文件后,result属性中包含所读取文件的原始二进制数据。 |
★readAsDataURL(file):void |
读取文件后,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。 |
★readAsText(file):void |
读取文件后,result属性中将包含一个字符串以表示所读取的文件内容。 |
事件名称 | 描述 |
---|---|
onabort |
当读取操作被中止时调用 |
onerror |
当读取操作发生错误时调用 |
★onload |
当读取操作成功完成时调用 |
onloadend |
当读取操作完成时调用,不管是成功还是失败 |
onloadstart |
当读取操作将要开始之前调用 |
onprogress |
在读取数据过程中周期性调用 |
注意:文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。
<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>
<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>
<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>
一般使用window.URL.createObjectURL()
方法比较多,主要用于获取文件对应的url。
注:加不加window.一般情况下没区别.
如果浏览器尚不支持URL()构造函数,则可以使用Window中的Window.URL (en-US)属性。
new URL()
属性 | 描述 |
---|---|
hash |
从#开始往后的所有信息 |
host |
域名+端口 |
hostname |
域名 |
href |
完整 URL |
pathname |
端口之后,以 ‘/’ 起头,#之前的文件路径 |
search |
指示 URL 的参数字符串; 如果提供了任何参数,则此字符串包括所有参数,并以开头的“?”开头 字符。 |
方法 | 描述 |
---|---|
toString() |
返回包含整个 URL字符串,它是URL.href的同义词,尽管它不能用于修改值。 |
toJSON() |
返回包含整个 URL 的字符串。 它返回与href属性相同的字符串。 |
方法 | 描述 |
---|---|
createObjectURL() |
返回一个字符串,包含一个唯一的 blob 链接(该链接协议为以 blob:,后跟唯一标识浏览器中的对象的掩码)方法参数:File对象和Blob对象 |
revokeObjectURL() |
销毁之前使用URL.createObjectURL()方法创建的 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>
<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>
一般用new Image(width,height)生成标签,结合图片预览使用
new Image([width,height])
创建了一个尚未被插入 DOM 树中的 HTMLImageElement 实例。
属性 | 描述 |
---|---|
alt |
表明图像的后备描述内容,会在图像无法加载时显示 |
src |
包含图像的完整的 URL,包含图像的基础 URL |
方法 | 描述 |
---|---|
decode() |
返回一个当图片解码后可安全用于附加到 DOM 上时 resolves 的 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)
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>
一个 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>