我们是否*必须*使用数据: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/ 中发现了一块煤,上面写着 HTMLImageElementsrc 属性 确实 实际上接受对象 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 );
}