题 在上传图像之前预览图像


我希望能够在上传之前预览文件(图像)。应该在浏览器中执行预览操作,而不使用Ajax上传图像。

我怎样才能做到这一点?


1180
2017-12-16 09:51


起源


请注意,除非您使用Gears或其他插件,否则无法在浏览器中操作图像: code.google.com/p/chromium/issues/detail?id=32276 - Steve-o
看看这个纯粹的JavaScript方法,包括它的答案以及Ray Nicholus对最终解决方案的评论: stackoverflow.com/questions/16430016/... - Jonathan Root
这是一篇很棒的详细文章,带有现场演示 codepedia.info/2015/06/... - Satinder singh
这是一个不使用jquery的简单解决方案: developer.mozilla.org/en-US/docs/Web/API/FileReader/... - John Gilmer
angulartutorial.net/2017/02/... - Prashobh


答案:


请看下面的示例代码:

function readURL(input) {

  if (input.files && input.files[0]) {
    var reader = new FileReader();

    reader.onload = function(e) {
      $('#blah').attr('src', e.target.result);
    }

    reader.readAsDataURL(input.files[0]);
  }
}

$("#imgInp").change(function() {
  readURL(this);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form1" runat="server">
  <input type='file' id="imgInp" />
  <img id="blah" src="#" alt="your image" />
</form>

还有,你可以 在这里试试这个样本


1943
2017-12-16 09:55



以上适用于我的XP上的Fx 3.6和Chrome。 - mplungjan
谢谢......你是一个节省生命的人:D当我说我在互联网上搜索了很多这个伎俩时,你的解决方案是唯一有效且相信我的解决方案。在gmail(撰写邮件 - >插入图片)上,他们会向您显示预览,但图像首先上传到他们的服务器上,然后在浏览器中显示。 - Igor Popov
谢谢...不能在IE 8中工作任何解决方案? - abhijit
仅在IE10及更高版本中支持FileReader API。 caniuse.com/filereader - Kelly Cook
为什么将jQuery用于`$('#blah')。attr('src',e.target.result);`什么时候可以简单地完成 document.getElementById('blah').src=e.target.result) - EasyBB


有几种方法可以做到这一点。最有效的方法是使用 URL.createObjectURL() 在...上 文件 从你的 <输入>。将此网址传递给 img.src 告诉浏览器加载提供的图像。

这是一个例子:

<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
  var loadFile = function(event) {
    var output = document.getElementById('output');
    output.src = URL.createObjectURL(event.target.files[0]);
  };
</script>

你也可以使用 FileReader.readAsDataURL() 解析<input>中的文件。这将在内存中创建一个包含图像的base64表示的字符串。

<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
  var loadFile = function(event) {
    var reader = new FileReader();
    reader.onload = function(){
      var output = document.getElementById('output');
      output.src = reader.result;
    };
    reader.readAsDataURL(event.target.files[0]);
  };
</script>


234
2017-11-27 08:17



仔细阅读:readAsDataURL和createObjectURL将在浏览器中缓存图像,然后返回base64编码的字符串,该字符串引用缓存中的图像位置。如果清除浏览器缓存,则base64编码的字符串将不再引用该图像。 base64字符串不是实际的图像数据,它是对图像的url引用,您不应将其保存到希望检索图像数据的数据库中。我最近犯了这个错误(约3分钟前)。 - tfmontague
@nkron感谢您的回复。但是,当视图在提交后从控制器返回时(在MVC中),图像会消失。即使这种情况,是否可以保留所选图像? - Clint Eastwood
@ H.Johnson,看一看 的sessionStorage。您可以将imageUR的dataURL版本保存到sessionStorage中,然后在返回页面时将其还原。 - nkron
根据浏览器规范使用(2)的第一个解决方案。 - Rob Scott
很好的答案。关于这段代码我还有一个问题:我怎样才能在以后撤销? URL.revokeObjectURL()释放内存,因为经过多次测试后变得非常慢。提前致谢。 - RaRdEvA


单线解决方案:

以下代码使用对象URL,这比查看大图像的数据URL更有效(数据URL是包含所有文件数据的大字符串,而对象URL,只是引用文件数据的短字符串 - 记忆):

<img id="blah" alt="your image" width="100" height="100" />

<input type="file" 
    onchange="document.getElementById('blah').src = window.URL.createObjectURL(this.files[0])">

生成的URL将如下:

blob:http%3A//localhost/7514bc74-65d4-4cf0-a0df-3de016824345

128
2017-11-18 20:00



版本通知:IE10 +支持 caniuse.com/#feat=bloburls - Raptor
到顶部:它只是工作,闪电般快,不依赖于jquery,它是一个真正的单行。如果你使用jquery $('your_selector').attr('src', window.URL.createObjectURL(this.files[0]))。无痛。谢谢。 - Cyril Duchon-Doris
@Raptor等等是整个File API ...(FileReader, input.files 等等。) URL.createObjectURL 是处理用户提交的文件时的方法,它只为用户磁盘上的真实文件创建一个内存符号链接。 - Kaiido
有没有办法在多个图像中使用它? - Rich
@丰富: this.files[0] 表示第一个(“第0个”)图像。只是循环 this.files 并且您可以使用多个图像来预览它们。 - Jesper


LeassTaTT的答案在FF和Chrome等“标准”浏览器中运行良好。 IE的解决方案存在,但看起来不同。这里描述跨浏览器解决方案:

在HTML中我们需要两个预览元素,img用于标准浏览器,div用于IE

HTML:

<img id="preview" 
     src="" 
     alt="" 
     style="display:none; max-width: 160px; max-height: 120px; border: none;"/>

<div id="preview_ie"></div>

在CSS中,我们指定以下IE特定的东西:

CSS:

#preview_ie {
  FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)
}  

在HTML中,我们包括标准和IE特定的Javascripts:

<script type="text/javascript">
  {% include "pic_preview.js" %}
</script>  
<!--[if gte IE 7]> 
<script type="text/javascript">
  {% include "pic_preview_ie.js" %}
</script>

pic_preview.js 是来自LeassTaTT答案的Javascript。更换 $('#blah') 连 $('#preview') 并添加 $('#preview').show()

现在IE特定的Javascript(pic_preview_ie.js):

function readURL (imgFile) {    
  var newPreview = document.getElementById('preview_ie');
  newPreview.filters.item('DXImageTransform.Microsoft.AlphaImageLoader').src = imgFile.value;
  newPreview.style.width = '160px';
  newPreview.style.height = '120px';
}    

那是。适用于IE7,IE8,FF和Chrome。请在IE9中测试并报告。 IE预览的想法在这里找到: http://forums.asp.net/t/1320559.aspx

http://msdn.microsoft.com/en-us/library/ms532969(v=vs.85).aspx


41
2017-12-24 11:58



在IE8 +中不起作用,因为通过javascript中的“imgFile.value”返回的路径不真实。从IE8开始,MS添加了一个安全功能,无法访问文件系统上的实际路径。 (唯一的办法是将网站添加到受信任的网站) - Jeff
刚刚在IE 7,8,9上测试过:效果很好!这很神奇,你是我的英雄:) Thx!不知道为什么,但样式过滤器属性直接div(style =“filter:...”)使它工作!
如果我想要撤消它怎么办,例如有一个选项“取消”取消图像预览 - medBo
不,它不在IE中工作.. - Raheel Hasan
我的情况:它适用于IE 7,8和9,但不适用于IE10 - Justin


我编辑了@Ivan的答案,显示“无预览可用”图像,如果它不是图像:

function readURL(input) {
    var url = input.value;
    var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
    if (input.files && input.files[0]&& (ext == "gif" || ext == "png" || ext == "jpeg" || ext == "jpg")) {
        var reader = new FileReader();

        reader.onload = function (e) {
            $('.imagepreview').attr('src', e.target.result);
        }

        reader.readAsDataURL(input.files[0]);
    }else{
         $('.imagepreview').attr('src', '/assets/no_preview.png');
    }
}

22
2018-06-05 06:23



但是当视图在提交后从控制器返回时(在MVC中),图像会消失。即使这种情况,是否可以保留所选图像? - Clint Eastwood
@Sachin Prasad,我们可以在上传之前在预览中设置最大文件数 - Super Model


这是一个 多个文件 版本,基于Ivan Baev的回答。

HTML

<input type="file" multiple id="gallery-photo-add">
<div class="gallery"></div>

JavaScript / jQuery

$(function() {
    // Multiple images preview in browser
    var imagesPreview = function(input, placeToInsertImagePreview) {

        if (input.files) {
            var filesAmount = input.files.length;

            for (i = 0; i < filesAmount; i++) {
                var reader = new FileReader();

                reader.onload = function(event) {
                    $($.parseHTML('<img>')).attr('src', event.target.result).appendTo(placeToInsertImagePreview);
                }

                reader.readAsDataURL(input.files[i]);
            }
        }

    };

    $('#gallery-photo-add').on('change', function() {
        imagesPreview(this, 'div.gallery');
    });
});

由于使用$ .parseHTML,需要jQuery 1.8,这应该有助于XSS缓解。

这将是开箱即用的,你需要的唯一依赖是jQuery。


14
2017-12-14 15:30



是否可以在每个<img>周围添加div标签,以及从预览/上传中删除它们的方法? - Rich
@Rich当然,只是玩它 - Nino Škopac


是。有可能的。

HTML

<input type="file" accept="image/*"  onchange="showMyImage(this)" />
 <br/>
<img id="thumbnil" style="width:20%; margin-top:10px;"  src="" alt="image"/>

JS

 function showMyImage(fileInput) {
        var files = fileInput.files;
        for (var i = 0; i < files.length; i++) {           
            var file = files[i];
            var imageType = /image.*/;     
            if (!file.type.match(imageType)) {
                continue;
            }           
            var img=document.getElementById("thumbnil");            
            img.file = file;    
            var reader = new FileReader();
            reader.onload = (function(aImg) { 
                return function(e) { 
                    aImg.src = e.target.result; 
                }; 
            })(img);
            reader.readAsDataURL(file);
        }    
    }

你可以得到 现场演示 从这里。


11
2017-07-25 11:20



dotnetk.com/image-preview-before-upload - Krunal Sisodiya


干净简单 的jsfiddle

当您希望从div或按钮间接触发事件时,这将非常有用。

<img id="image-preview"  style="height:100px; width:100px;"  src="" >

<input style="display:none" id="input-image-hidden" onchange="document.getElementById('image-preview').src = window.URL.createObjectURL(this.files[0])" type="file" accept="image/jpeg, image/png">

<button  onclick="HandleBrowseClick('input-image-hidden');" >UPLOAD IMAGE</button>


<script type="text/javascript">
function HandleBrowseClick(hidden_input_image)
{
    var fileinputElement = document.getElementById(hidden_input_image);
    fileinputElement.click();
}     
</script>

7
2017-11-30 05:57



完美,谢谢分享,我得到预览图像的网址?我需要通过PHP上传它。谢谢! - xscoder
请注意:我不能相信这一点,但你可以使用 <label> 并避免javascript完全处理按钮单击。 使用纯HTML / CSS触发文件输入。,它根本不是hacky。 - Regular Joe


使用JavaScript(jQuery)和HTML5的多个图像的示例

JavaScript(jQuery)

function readURL(input) {
     for(var i =0; i< input.files.length; i++){
         if (input.files[i]) {
            var reader = new FileReader();

            reader.onload = function (e) {
               var img = $('<img id="dynamic">');
               img.attr('src', e.target.result);
               img.appendTo('#form1');  
            }
            reader.readAsDataURL(input.files[i]);
           }
        }
    }

    $("#imgUpload").change(function(){
        readURL(this);
    });
}

标记(HTML)

<form id="form1" runat="server">
    <input type="file" id="imgUpload" multiple/>
</form>

6
2017-11-26 06:33