Open FrankKai opened 5 years ago
const blob = new Blob([new Uint8Array(arrayBuffer)], { type: 'audio/AMR' });
提醒:尤其第三点,涉及到了内存管理,一定要注意释放内存
vue的单文件组件共有一个document,这也是它被称为单页应用的原因,因此可以在组件间直接通过blob URL进行通信。 在vue-router采用hash模式的情况下,页面间的路由跳转,不会重新加载整个页面,所以URL的生命周期非常强力,因此在跨页面(非新tab)的组件通信,也可以使用blob URL。 需要注意的是,在vue的hash mode模式下,需要更加注意通过URL.revokeObjectURL()进行的内存释放,在大量使用blob URL的情况下,可能会撑爆浏览器内存
<label for="background">上传背景</label>
<input type="file" style="display: none"
id="background" name="background"
accept="image/png, image/jpeg" multiple="false"
@change="backgroundUpload"
>
backgroundUpload(event) {
const fileBlobURL = window.URL.createObjectURL(event.target.files[0]);
this.$emit('background-change', fileBlobURL);
// this.$bus.$emit('background-change', fileBlobURL);
},
<BackgroundUploader @background-change="backgroundChangeHandler"></BackgroundUploader>
// this.$bus.$on("background-change", backgroundChangeHandler);
backgroundChangeHandler(url) {
// some code handle blob url...
},
暂时没有找到方法获取所有的blob URL,但是可以通过sessionStorage和localStorage进行标记,通过key进行更新或者访问。 若是没有新tab的纯单页应用的跨组件通信,可以存储在sessionStorage或者localStorage;若是存在新的tab,blob URL跨tab已经失效,需要存储最原始的数据类型,使用时再进行转换。 需要注意的是,在一个blob URL使用结束后,需要从storage和内存中同时删除。
提醒:如果你的项目会涉及到多个tab间的通信,blob URL在另一个tab中是无效的。可以存储原始数据,使用时再转换为blob URL
本地预览仅仅适用于浏览器预览,当需要持久化存储时,就需要将其上传到云存储上,现在用处比较广泛的是OSS、七牛云等公有云,私有云没接触过,应该是大同小异。 如果是上传到云存储,一个仅在当前document内生命周期的blob url就不生效了,那么就需要上传有效的数据上去,就我目前接触的项目来说,我们是将文件最终转换成base64格式,通过接入sdk接口的服务端接口实现上传。 那么问题来了,如果是canvas,可以通过toDataURL()转换为base64,第三方的canvas库也提供相同的api。可以将blob url转换为base64吗?那么如何将File,Blob对象转换为base64格式?
不可以。
用到一个神奇的对象:Reader对象 用到一个神奇的方法:readAsDataURL(blob) 当文件完成读取并成功转换后,会触发loadend事件,同时会在Reader实例的result属性中存储base64格式的数据。 若是比较抽象,可以看下面的示例:
transferBlobFileToBase64(file){
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = async function() {
const fileBase64 = reader.result;
// 下面的接口是一个接入了七牛sdk的接口,通过base64str接收base64格式数据,返回一个hash
const { hash } = await uploadQiNiu({ base64Str: fileBase64 });
// 根据环境对hash进行拼接,生成一个可访问的url并且存储到持久层(mysql, elastic search, tablestore, whatever)
};
}
若需要上传以后传递到其他方法进行数据组装,可以采用下面的方法:
async transferBlobFileToBase64(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = async function() {
const fileBase64 = reader.result;
const { hash } = await uploadQiNiu({ base64Str: fileBase64 });
resolve(`${pageConfig.QINIU_IMG_URL}/${hash}`);
};
});
},
async serverAPIRevoke(file) {
const uploadedFile = await this.transferBlobFileToBase64(file);
// 在这里进行数据的组装并且调用服务端接口持久化存储
}
var newBlob = new Blob(array, options);
// array是个数组:数组元素可以是ArrayBuffer,ArrayBufferView, Blob, USVString
普通的 ‘foo’也可以作为生成Blob对象。
var blob = new Blob(['foo'],{type:'text/plain'})
blob.text().then((data)=>{console.log(data)})// 'foo'
这样就生成一个最简易的blob对象了,可以用来测试一些api。
fetch(url).then(response => response.blob()).then((blob)=>{
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL( blob );
const img = new Image();
img.crossOrigin = 'Anonymous'; // CORS
img.src = imageUrl;
})
// Simulate a call to Dropbox or other service that can
// return an image as an ArrayBuffer.
const xhr = new XMLHttpRequest();
// Use JSFiddle logo as a sample image to avoid complicating
// this example with cross-domain issues.
xhr.open( "GET", url, true );
// Ask for the result as an ArrayBuffer.
xhr.responseType = "arraybuffer";
xhr.onload = function( e ) {
// Obtain a blob: URL for the image data.
const arrayBufferView = new Uint8Array( this.response );
const blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL( blob );
const img = new Image();
img.crossOrigin = 'Anonymous'; // CORS
img.src = imageUrl;
};
xhr.send();
问题源于此帖:https://www.v2ex.com/t/648393#reply3 XHR思路源于:https://jsfiddle.net/Jan_Miksovsky/yy7Zs 可测试图片:https://img.thedailybeast.com/image/upload/c_crop,d_placeholder_euli9k,h_1439,w_2560,x_0,y_0/dpr_1.5/c_limit,w_1044/fl_lossy,q_auto/v1492791705/articles/2013/01/17/why-the-lakers-kobe-bryant-and-wife-vanessa-are-staying-together/130114-Samuels-Kobe-divorce-01_pfkz0r
先看一下blob URL长什么样:
http/https协议前加了一个blob:,是不是看起来很神奇,其实它不仅看起来神奇,在前端开发领域用处也十分广泛。
blob对象在前端开发中是非常常见的,下面我将列举几个应用场景:
<input type="file" />
上传文件之后的File对象,最初只想在本地留存,时机合适再上传到服务器blob仅仅是一种数据对象,在上述2个场景中,都需要比较重要的一个API,那就是
window.URL.createObjectURL()
。所以我们在介绍blob对象之余,也会对这个关键的API进行介绍。所以文章主要分为以下几个部分:
<input type="file" />
场景下的blobwindow.URL.createObjectURL()