【问题标题】:Loading an image to a <img> from <input file>从 <input file> 将图像加载到 <img>
【发布时间】:2011-04-18 08:56:26
【问题描述】:

我正在尝试通过元素加载用户选择的图像。

我向输入元素添加了一个 onchange 事件处理程序,如下所示:

<input type="file" name="picField" id="picField" size="24" onchange="preview_2(this);" alt=""/>

preview_2 函数是:

var outImage ="imagenFondo";
function preview_2(what){
    globalPic = new Image();
    globalPic.onload = function() {
        document.getElementById(outImage).src = globalPic.src;
    }
    globalPic.src=what.value;
}

其中 outImage 是我希望加载新图片的标签的 id 值。

但是,onload 似乎永远不会发生,并且它不会将任何内容加载到 html。

我该怎么办?

【问题讨论】:

标签: javascript html


【解决方案1】:

在支持File API的浏览器中,一旦用户选择了文件,您就可以使用FileReader构造函数来读取文件。

示例

document.getElementById('picField').onchange = function (evt) {
    var tgt = evt.target || window.event.srcElement,
        files = tgt.files;

    // FileReader support
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            document.getElementById(outImage).src = fr.result;
        }
        fr.readAsDataURL(files[0]);
    }

    // Not supported
    else {
        // fallback -- perhaps submit the input to an iframe and temporarily store
        // them on the server until the user's session ends.
    }
}

浏览器支持

  • IE 10
  • Safari 6.0.2
  • 铬 7
  • 火狐3.6
  • Opera 12.02

在不支持文件 API 的情况下,您无法(在大多数注重安全的浏览器中)从文件输入框中获取文件的完整路径,也无法访问数据。唯一可行的解​​决方案是将表单提交到隐藏的 iframe 并将文件预上传到服务器。然后,当该请求完成时,您可以将图像的 src 设置为上传文件的位置。

【讨论】:

  • 对,所以我无法像听起来那样简单地上传从用户那里选择的图像......?
  • 是的,我正在寻找 x 浏览器解决方案,所以我想我会尝试使用服务器选项。非常感谢!
  • 我想知道为什么将其转换为 DataURL 而不仅仅是对象 url?
  • 如果要同步版本,可以使用:URL.createObjectURL(document.getElementById("fileInput").files[0]);
  • @КонстантинВан 你必须确保调用URL.revokeObjectURL 以防止内存泄漏! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
【解决方案2】:

正如 iEamin 在他的回答中所说,HTML 5 现在确实支持这一点。他提供的链接http://www.html5rocks.com/en/tutorials/file/dndfiles/ 非常棒。以下是基于该站点示例的最小示例,但请参阅该站点以获取更详尽的示例。

onchange 事件监听器添加到您的 HTML:

<input type="file" onchange="onFileSelected(event)">

制作带有 id 的图像标签(我指定 height=200 以确保图像在屏幕上不会太大):

<img id="myimage" height="200">

这里是 onchange 事件监听器的 JavaScript。它接受作为event.target.files[0] 传递的File 对象,构造一个FileReader 来读取其内容,并设置一个新的事件侦听器以将生成的data: URL 分配给img 标记:

function onFileSelected(event) {
  var selectedFile = event.target.files[0];
  var reader = new FileReader();

  var imgtag = document.getElementById("myimage");
  imgtag.title = selectedFile.name;

  reader.onload = function(event) {
    imgtag.src = event.target.result;
  };

  reader.readAsDataURL(selectedFile);
}

【讨论】:

  • 很好的链接!不过,您为脚本提供的代码尚未定义。
【解决方案3】:

$('document').ready(function () {
    $("#imgload").change(function () {
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#imgshow').attr('src', e.target.result);
            }
            reader.readAsDataURL(this.files[0]);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="imgload" >
<img src="#" id="imgshow" align="left">

这在 jQuery 中对我有用。

【讨论】:

  • 如果 'imgload' 和 'imgshow' 没有预先定义,如何使用?假设我有 5 对从服务器返回的文件输入和图像持有者,它们各自的 id 是根据服务器代码返回的一些索引生成的。
【解决方案4】:

ES2017 方式

// convert file to a base64 url
const readURL = file => {
    return new Promise((res, rej) => {
        const reader = new FileReader();
        reader.onload = e => res(e.target.result);
        reader.onerror = e => rej(e);
        reader.readAsDataURL(file);
    });
};

// for demo
const fileInput = document.createElement('input');
fileInput.type = 'file';
const img = document.createElement('img');
img.attributeStyleMap.set('max-width', '320px');
document.body.appendChild(fileInput);
document.body.appendChild(img);

const preview = async event => {
    const file = event.target.files[0];
    const url = await readURL(file);
    img.src = url;
};

fileInput.addEventListener('change', preview);

【讨论】:

    【解决方案5】:

    Andy E 是正确的,没有基于 HTML 的方法可以做到这一点*;但如果你愿意使用 Flash,你可以做到。以下内容在安装了 Flash 的系统上可靠运行。如果您的应用需要在 iPhone 上运行,那么您当然需要一个基于 HTML 的备用解决方案。

    *(2013 年 4 月 22 日更新:HTML 现在在 HTML5 中支持此功能。请参阅其他答案。)

    Flash 上传还有其他优点——Flash 让您能够在上传大文件时显示进度条。 (我很确定 Gmail 就是这样做的,通过在幕后使用 Flash,尽管我可能错了。)

    这是一个示例 Flex 4 应用程序,它允许用户选择一个文件,然后显示它:

    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
                   creationComplete="init()">
        <fx:Declarations>
            <!-- Place non-visual elements (e.g., services, value objects) here -->
        </fx:Declarations>
        <s:Button x="10" y="10" label="Choose file..." click="showFilePicker()" />
        <mx:Image id="myImage" x="9" y="44"/>
        <fx:Script>
            <![CDATA[
                private var fr:FileReference = new FileReference();
    
                // Called when the app starts.
                private function init():void
                {
                    // Set up event handlers.
                    fr.addEventListener(Event.SELECT, onSelect);
                    fr.addEventListener(Event.COMPLETE, onComplete);
                }
    
                // Called when the user clicks "Choose file..."
                private function showFilePicker():void
                {
                    fr.browse();
                }
    
                // Called when fr.browse() dispatches Event.SELECT to indicate
                // that the user has picked a file.
                private function onSelect(e:Event):void
                {
                    fr.load(); // start reading the file
                }
    
                // Called when fr.load() dispatches Event.COMPLETE to indicate
                // that the file has finished loading.
                private function onComplete(e:Event):void
                {
                    myImage.data = fr.data; // load the file's data into the Image
                }
            ]]>
        </fx:Script>
    </s:Application>
    

    【讨论】:

    • 澄清一下,对于那些担心安全性的人:Flash 不允许您访问任何本地文件——它只允许您访问已明确、交互指向的本地文件用户。这类似于 HTML 所做的(它允许您将任何明确指定的文件上传到服务器),除了 Flash 还允许本地访问以及上传文件的能力。
    • 我在这里上传了可执行的 Flash 应用,你可以试试:morearty.com/preview/FileUploadTest.html
    【解决方案6】:

    var outImage ="imagenFondo";
    function preview_2(obj)
    {
    	if (FileReader)
    	{
    		var reader = new FileReader();
    		reader.readAsDataURL(obj.files[0]);
    		reader.onload = function (e) {
    		var image=new Image();
    		image.src=e.target.result;
    		image.onload = function () {
    			document.getElementById(outImage).src=image.src;
    		};
    		}
    	}
    	else
    	{
    		    // Not supported
    	}
    }
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>preview photo</title>
    </head>
    
    <body>
    <form>
    	<input type="file" onChange="preview_2(this);"><br>
    	<img id="imagenFondo" style="height: 300px;width: 300px;">
    </form>
    </body>
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-29
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2023-04-02
      相关资源
      最近更新 更多