使用Javascript在文件上传期间获取图像尺寸

13

我有一个文件上传的UI元素,用户将上传图像。在这里,我必须在客户端验证图像的高度和宽度。是否有可能使用JS仅通过文件路径查找图像的大小?

注意:如果不行,是否有其他方法可以在客户端找到图像的尺寸?

5个回答

22
您可以在支持 W3C 的新文件 API的浏览器上执行此操作,使用FileReader接口上的readAsDataURL函数,并将数据 URL 分配给 imgsrc(之后您可以读取图像的 heightwidth)。目前 Firefox 3.6 支持 File API,我认为 Chrome 和 Safari 要么已经支持,要么即将支持。

因此,在过渡阶段,您的逻辑应该是这样的:

  1. 检测浏览器是否支持 File API(很容易: if (typeof window.FileReader === 'function'))。

  2. 如果支持,那就太好了,可以在本地读取数据并将其插入到图像中以查找其尺寸。

  3. 如果不支持,则将文件上传到服务器(可能会从 iframe 提交表单以避免离开页面),然后轮询服务器询问图像的大小(或者只是请求已上传的图像,如果您喜欢的话)。

编辑 我一直想制作一个文件 API 的示例,现在给大家展示一下:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Show Image Dimensions Locally</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script type='text/javascript'>

    function loadImage() {
        var input, file, fr, img;

        if (typeof window.FileReader !== 'function') {
            write("The file API isn't supported on this browser yet.");
            return;
        }

        input = document.getElementById('imgfile');
        if (!input) {
            write("Um, couldn't find the imgfile element.");
        }
        else if (!input.files) {
            write("This browser doesn't seem to support the `files` property of file inputs.");
        }
        else if (!input.files[0]) {
            write("Please select a file before clicking 'Load'");
        }
        else {
            file = input.files[0];
            fr = new FileReader();
            fr.onload = createImage;
            fr.readAsDataURL(file);
        }

        function createImage() {
            img = document.createElement('img');
            img.onload = imageLoaded;
            img.style.display = 'none'; // If you don't want it showing
            img.src = fr.result;
            document.body.appendChild(img);
        }

        function imageLoaded() {
            write(img.width + "x" + img.height);
            // This next bit removes the image, which is obviously optional -- perhaps you want
            // to do something with it!
            img.parentNode.removeChild(img);
            img = undefined;
        }

        function write(msg) {
            var p = document.createElement('p');
            p.innerHTML = msg;
            document.body.appendChild(p);
        }
    }

</script>
</head>
<body>
<form action='#' onsubmit="return false;">
<input type='file' id='imgfile'>
<input type='button' id='btnLoad' value='Load' onclick='loadImage();'>
</form>
</body>
</html>

在Firefox 3.6上运行良好。我避免使用任何库,因此对于属性(DOM0)样式事件处理程序等表示歉意。


我使用了您提供的解决方案,在通过iOS Safari上传图像之前检查其方向(因为iOS在上传过程中会剥离很多exif数据,例如方向)。我发现如果图像具有display:none属性(在纵向模式下混淆宽度和高度),则该解决方案会得到错误的尺寸。我的解决方法是给它一个左侧-10000px或更多的绝对位置。无论如何,感谢您的工作。它让我免去了很多额外的麻烦。 - stafffan

9
前面的例子还可以,但还远非完美。
var reader  = new FileReader();

reader.onload   = function(e)
{
    var image   = new Image();

    image.onload    = function()
    {
        console.log(this.width, this.height);
    };

    image.src   = e.target.result;
};

reader.readAsDataURL(this.files[0]);

很酷!但在我的情况下,JS在第二次点击上传按钮后立即写入控制台。出了什么问题? - Subtle Fox
哦,找到了答案:应该在<input>元素中使用“onchange”事件而不是“onclick”。无论如何,感谢Gajus。 - Subtle Fox

1
如果您使用像SWFUpload这样的基于Flash的上传工具,您可以获得所有所需的信息以及多个排队上传。
我推荐SWFUpload,并且除了作为用户之外,与他们没有任何关联。
您还可以编写一个Silverlight控件来选择文件并上传。

当然,这需要您的用户允许Flash。由于所有基于Flash的广告,我们中的很多人都会默认屏蔽Flash。 - T.J. Crowder
@TJC 确实如此,但在 HTML5 普及之前,Flash/ActiveX/Silverlight/XBap 是这种情况下唯一可行的选择。 - Sky Sanders
诗人:确实是这样。:-) 对我来说,我只会做HTML5或服务器端,但肯定有一个选项是HTML5,回退到(插入专有技术),回退到服务器端。 :-) - T.J. Crowder
@TJC - 这总是所有新玩具(如HTML5和本地JSON)最令人沮丧的方面 - 在它们变得普及之前,从生产角度来看,它们只不过是小小的新奇玩意。我们仍然支持IE6,真是让人哭笑不得! - Sky Sanders

0
不可以,文件名和文件内容是通过HTTP请求的正文发送到服务器的,JavaScript无法操作这些字段。

有没有其他方法在客户端找到尺寸? - Gopi
你需要将它上传到其他地方,在服务器上进行检查,并通过ajax获取这些值。 - YOU
我不确定 Flash 能否做到,但 Java applet 应该可以做到。或者看起来 HTML5 可以做到,参见 T.J. Crowder 的回答。 - YOU
欢迎!看起来 Flash 也可以做到。你可以看一下代码诗人的回答。Flash 应该在客户端完成。 - YOU

0

HTML5 绝对是这里的正确解决方案。 你应该始终为未来编写代码,而不是过去。 处理 HTML4 浏览器的最佳方法是要么回退到降级功能,要么使用 Flash(但仅在浏览器不支持 HTML5 文件 API 的情况下)

使用 img.onload 事件将使您能够恢复文件的尺寸。 它正在我正在开发的应用程序中工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接