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

IT技术 asp.net javascript image validation file-upload
2021-01-23 11:59:10

我有文件上传 UI 元素,用户将在其中上传图像。在这里,我必须在客户端验证图像的高度和宽度。是否可以在JS中找到只有文件路径的图像的大小?

注意:如果没有,是否还有其他方法可以在客户端找到维度?

5个回答

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

所以你在过渡阶段的逻辑是这样的:

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

  2. 如果是这样,很好,在本地读取数据并将其插入图像中以查找尺寸。

  3. 如果没有,将文件上传到服务器(可能从 iframe 提交表单以避免离开页面),然后轮询服务器询问图像有多大(或者只是询问上传的图像,如果你愿意的话)。

编辑一段时间以来,我一直想编写一个 File 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 左右的绝对位置。不管怎样,谢谢你的工作。它使我免于许多额外的头痛。
2021-04-07 11:59:10

前面的例子是好的,但它远非完美。

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]);
哦,找到了一个答案:它应该是 <input> 元素中 'onclick' 的 'onchange' 事件。不管怎样,谢谢Gajus
2021-03-29 11:59:10
凉爽的!但在我的情况下,JS 在第二次点击上传按钮后立即写入控制台。怎么了?
2021-04-13 11:59:10

如果您使用基于 Flash 的上传,例如 SWFUpload,您可以获得所需的所有信息以及多个排队上传。

我推荐 SWFUpload,除了作为用户之外,我与它们没有任何关联。

您还可以编写一个 Silverlight 控件来选择您的文件并上传它。

诗人:确实如此。:-) 对我来说,我只做 HTML5 或服务器端,但肯定有一个选项是 HTML5,回退到(在此处插入专有技术),回退到服务器端。:-)
2021-03-19 11:59:10
@TJC——这始终是所有新玩具(如 HTML5 和原生 JSON)真正令人沮丧的方面——直到它们无处不在,从生产的角度来看,它们只不过是新奇。我们仍然支持IE6大声哭!
2021-03-22 11:59:10
当然,这需要您的用户允许 Flash。由于所有基于 Flash 的广告,我们中的很多人暂时阻止 Flash 是理所当然的。
2021-04-03 11:59:10
@TJC 同意,但在 HTML5 无处不在之前,Flash/ActiveX/Silverlight/XBap 是这种情况的唯一可行选择。
2021-04-09 11:59:10

不,您不能,文件名和文件内容在 http标头正文中发送到服务器,javascript 无法操作这些字段。

有没有其他方法可以在客户端找到维度?
2021-03-18 11:59:10
我不确定 flash 能不能做到,但 java applet 应该能做到。或者看起来 html5 可以做到这一点,请参阅 TJ Crowder 的回答
2021-03-19 11:59:10
欢迎!,貌似flash也可以。你可以看看代码诗人的答案。flash应该在客户端完成
2021-03-28 11:59:10
您需要将其上传到其他地方,在服务器中检查并使用 ajax 取回这些值
2021-04-12 11:59:10

HTML5 绝对是这里的正确解决方案。您应该始终为未来而不是过去编码。处理 HTML4 浏览器的最佳方法是退回降级的功能或使用 Flash(但前提是浏览器不支持 HTML5 文件 API)

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