我们是否*必须*使用数据:URI (readAsDataURL) 以在 JavaScript 中使用具有 <img /> 的文件对象?
Do we *have* to use data: URIs (readAsDataURL) to use File objects with <img /> in JavaScript?
我理解当前从客户端 File
对象在 JavaScript 中创建 <img />
元素的常用技术是这样的。
(File
对象将源自文件拖放处理程序或 <input type="file" />
change
事件。)
function showImageFile( file: File ): void {
let rdr = new FileReader();
rdr.readAsDataURL( file );
rdr.onloadend = function() {
let img = document.createElement('img');
img.src = rdr.result;
document.body.appendChild( img );
};
}
我不喜欢这个 - 将可能是数兆字节的图像序列化为 base64 编码字符串的概念(因此使用 1.3x more 内存现有的 File
对象)以及将字符串反序列化回 <img />
元素的成本 - 最终这将导致至少 3 个图像数据实例存在于内存中。这对我来说似乎非常浪费和低效,而且 JavaScript 应用程序已经因过度内存消耗而声名狼藉。
我注意到对于 <video>
和 <audio>
元素 (HTMLMediaElement
),MDN 建议这样做:
function showVideoFile( file: File ): void {
let video = document.createElement('video');
video.srcObject = URL.createObjectURL( file ); // createObjectURL creates a URI alias to the existing file instance in-memory
}
(注意如果 srcObject
被替换或 video
元素被移除,之前的 objectURL
必须使用 revokeObjectURL
手动释放。
有什么方法可以为 <img />
做同样的事情吗? (我在 HTMLImageElement
上没有看到 srcObject
属性 并且 HTMLImageElement
不是从 HTMLMediaElement
派生的。不幸的是,在线搜索 "javascript image files without data URIs" 只有 returns 页 about readAsDataURL
这与我想要的相反。
你设置它…src
.
document.getElementById('file').onchange = function () {
if (this.files.length !== 0) {
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
document.body.appendChild(img);
}
};
<input type="file" id="file" accept="image/*" />
在 Google 的黑暗和肮脏的信息矿井中牺牲了更多的时间后,我在 2014 年 12 月的这篇文章 http://bytes.schibsted.com/the-magic-of-createobjecturl/ 中发现了一块煤,上面写着 HTMLImageElement
的 src
属性 确实 实际上接受对象 URI(呸!)
MDN 也在他们的网站上对其进行了介绍,尽管有些隐蔽:https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images
简而言之,我的 showImageFile
函数可以这样更新:
function showImageFile( file: File ): void {
let objectURI = URL.createObjectURL( file ); // looks like "blob:http://mywebsite/{guid}"
let img = document.createElement('img');
img.src = objectURI ;
document.body.appendChild( img );
}
或者如果 img
元素将被重复使用:
var img: HTMLImageElement;
function showImageFile( file: File ): void {
let oldSrc = img.src;
let objectURI = URL.createObjectURL( file );
img.src = objectURI;
if( oldSrc ) URL.revokeObjectURL( oldSrc );
}
我理解当前从客户端 File
对象在 JavaScript 中创建 <img />
元素的常用技术是这样的。
(File
对象将源自文件拖放处理程序或 <input type="file" />
change
事件。)
function showImageFile( file: File ): void {
let rdr = new FileReader();
rdr.readAsDataURL( file );
rdr.onloadend = function() {
let img = document.createElement('img');
img.src = rdr.result;
document.body.appendChild( img );
};
}
我不喜欢这个 - 将可能是数兆字节的图像序列化为 base64 编码字符串的概念(因此使用 1.3x more 内存现有的 File
对象)以及将字符串反序列化回 <img />
元素的成本 - 最终这将导致至少 3 个图像数据实例存在于内存中。这对我来说似乎非常浪费和低效,而且 JavaScript 应用程序已经因过度内存消耗而声名狼藉。
我注意到对于 <video>
和 <audio>
元素 (HTMLMediaElement
),MDN 建议这样做:
function showVideoFile( file: File ): void {
let video = document.createElement('video');
video.srcObject = URL.createObjectURL( file ); // createObjectURL creates a URI alias to the existing file instance in-memory
}
(注意如果 srcObject
被替换或 video
元素被移除,之前的 objectURL
必须使用 revokeObjectURL
手动释放。
有什么方法可以为 <img />
做同样的事情吗? (我在 HTMLImageElement
上没有看到 srcObject
属性 并且 HTMLImageElement
不是从 HTMLMediaElement
派生的。不幸的是,在线搜索 "javascript image files without data URIs" 只有 returns 页 about readAsDataURL
这与我想要的相反。
你设置它…src
.
document.getElementById('file').onchange = function () {
if (this.files.length !== 0) {
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
document.body.appendChild(img);
}
};
<input type="file" id="file" accept="image/*" />
在 Google 的黑暗和肮脏的信息矿井中牺牲了更多的时间后,我在 2014 年 12 月的这篇文章 http://bytes.schibsted.com/the-magic-of-createobjecturl/ 中发现了一块煤,上面写着 HTMLImageElement
的 src
属性 确实 实际上接受对象 URI(呸!)
MDN 也在他们的网站上对其进行了介绍,尽管有些隐蔽:https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images
简而言之,我的 showImageFile
函数可以这样更新:
function showImageFile( file: File ): void {
let objectURI = URL.createObjectURL( file ); // looks like "blob:http://mywebsite/{guid}"
let img = document.createElement('img');
img.src = objectURI ;
document.body.appendChild( img );
}
或者如果 img
元素将被重复使用:
var img: HTMLImageElement;
function showImageFile( file: File ): void {
let oldSrc = img.src;
let objectURI = URL.createObjectURL( file );
img.src = objectURI;
if( oldSrc ) URL.revokeObjectURL( oldSrc );
}