【问题标题】:Check image width and height before upload with Javascript在使用 Javascript 上传之前检查图像的宽度和高度
【发布时间】:2012-02-12 19:14:23
【问题描述】:

我有一个 JPS,用户可以在其中放置图像:

<div class="photo">
    <div>Photo (max 240x240 and 100 kb):</div>
    <input type="file" name="photo" id="photoInput" onchange="checkPhoto(this)"/>
</div>

我已经写了这个js:

function checkPhoto(target) {
    if(target.files[0].type.indexOf("image") == -1) {
        document.getElementById("photoLabel").innerHTML = "File not supported";
        return false;
    }
    if(target.files[0].size > 102400) {
        document.getElementById("photoLabel").innerHTML = "Image too big (max 100kb)";
        return false;
    }
    document.getElementById("photoLabel").innerHTML = "";
    return true;
}

它可以很好地检查文件类型和大小。现在我想检查图像的宽度和高度,但我做不到。
我试过target.files[0].width,但我得到undefined。通过其他方式我得到0
有什么建议吗?

【问题讨论】:

    标签: javascript image file-upload image-size


    【解决方案1】:
    function validateimg(ctrl) {
        var fileUpload = $("#txtPostImg")[0];
        var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(.jpg|.png|.gif)$");
        if (regex.test(fileUpload.value.toLowerCase())) {
            if (typeof (fileUpload.files) != "undefined") {
                var reader = new FileReader();
                reader.readAsDataURL(fileUpload.files[0]);
                reader.onload = function (e) {
                    var image = new Image();
                    image.src = e.target.result;
                    image.onload = function () {
                        var height = this.height;
                        var width = this.width;
                        console.log(this);
                        if ((height >= 1024 || height <= 1100) && (width >= 750 || width <= 800)) {
                            alert("Height and Width must not exceed 1100*800.");
                            return false;
                        }
                        alert("Uploaded image has valid Height and Width.");
                        return true;
                    };
                }
            } else {
                alert("This browser does not support HTML5.");
                return false;
            }
        } else {
            alert("Please select a valid Image file.");
            return false;
        }
    }
    

    【讨论】:

    • 请尝试格式化完整的代码并简要说明您在代码中所做的工作。
    【解决方案2】:

    我同意。一旦它被上传到用户浏览器可以访问的地方,那么很容易获得大小。由于您需要等待图像加载,您需要为img 挂钩到onload 事件。

    更新示例:

    
    // async/promise function for retrieving image dimensions for a URL
    function imageSize(url) {
        const img = document.createElement("img");
    
        const promise = new Promise((resolve, reject) => {
          img.onload = () => {
            // Natural size is the actual image size regardless of rendering.
            // The 'normal' `width`/`height` are for the **rendered** size.
            const width  = img.naturalWidth;
            const height = img.naturalHeight; 
    
            // Resolve promise with the width and height
            resolve({width, height});
          };
    
          // Reject promise on error
          img.onerror = reject;
        });
    
        // Setting the source makes it start downloading and eventually call `onload`
        img.src = url;
    
        return promise;
    }
    
    // How to use in an async function
    (async() => {
      const imageUrl = 'http://your.website.com/userUploadedImage.jpg';
      const imageDimensions = await imageSize(imageUrl);
    
      console.info(imageDimensions); // {width: 1337, height: 42}
    })();
    
    

    旧示例:

    var width, height;
    
    var img = document.createElement("img");
    img.onload = function() {
        // `naturalWidth`/`naturalHeight` aren't supported on <IE9. Fallback to normal width/height
        // The natural size is the actual image size regardless of rendering.
        // The 'normal' width/height are for the **rendered** size.
        
        width  = img.naturalWidth  || img.width;
        height = img.naturalHeight || img.height; 
        
        // Do something with the width and height
    }
    
    // Setting the source makes it start downloading and eventually call `onload`
    img.src = "http://your.website.com/userUploadedImage.jpg";
    

    【讨论】:

      【解决方案3】:

      就我而言,我还需要阻止提交表单,所以这是对我有用的解决方案。

      preventDefault 将停止表单动作,然后我们在 onload 函数中检查图像的大小和尺寸。

      如果一切顺利,我们允许提交。

      如果用户仍然尝试使用无效图像提交表单,则提交按钮会被禁用,因此我还必须在输入有效图像后重新启用提交按钮。

      const validateMaxImageFileSize = (e) => {
        e.preventDefault();
        const el = $("input[type='file']")[0];
      
        if (el.files && el.files[0]) {
          const file = el.files[0];
      
          const maxFileSize = 5242880; // 5 MB
          const maxWidth = 1920;
          const maxHeight = 1080;
      
          const img = new Image();
          img.src = window.URL.createObjectURL(file);
          img.onload = () => {
            if (file.type.match('image.*') && file.size > maxFileSize) {
              alert('The selected image file is too big. Please choose one that is smaller than 5 MB.');
            } else if (file.type.match('image.*') && (img.width > maxWidth || img.height > maxHeight)) {
              alert(`The selected image is too big. Please choose one with maximum dimensions of ${maxWidth}x${maxHeight}.`);
            } else {
              e.target.nodeName === 'INPUT'
                ? (e.target.form.querySelector("input[type='submit']").disabled = false)
                : e.target.submit();
            }
          };
        }
      };
      
      $('form.validate-image-size').on('submit', validateMaxImageFileSize);
      $("form.validate-image-size input[type='file']").on('change', validateMaxImageFileSize);
      

      【讨论】:

        【解决方案4】:

        在我看来,您必须要求的完美答案是

        var reader = new FileReader();
        
        //Read the contents of Image File.
        reader.readAsDataURL(fileUpload.files[0]);
        reader.onload = function (e) {
        
          //Initiate the JavaScript Image object.
          var image = new Image();
        
          //Set the Base64 string return from FileReader as source.
          image.src = e.target.result;
        
          //Validate the File Height and Width.
          image.onload = function () {
            var height = this.height;
            var width = this.width;
            if (height > 100 || width > 100) {
              alert("Height and Width must not exceed 100px.");
              return false;
            }
            alert("Uploaded image has valid Height and Width.");
            return true;
          };
        };
        

        【讨论】:

        • 一个很好的答案,因为它不需要createObjectUrl。可以改进为使用reader.result 而不是e.target.result 并且应该使用reader.onloadend 而不是onload 结合reader.onerror 来处理错误
        • 我用 13 MB 的图像文件尝试了代码。在浏览器中处理和返回宽度/高度最多需要 2 秒。然而,最佳答案是在几毫秒内获得图像尺寸。
        • @Avatar 您应该说明谁发布了最佳答案,因为最佳答案会随着时间而变化。
        • 好点。我的意思是:stackoverflow.com/a/8904008/1066234
        【解决方案5】:

        您可以在不显示图像的情况下执行预览步骤,所有浏览器都支持。以下 js 代码向您展示了如何检查 widthheight

        var file = e.target.files[0];
        if (/\.(jpe?g|png|gif)$/i.test(file.name)) {
            var reader = new FileReader();
            reader.addEventListener("load", function () {
                var image = new Image();
                image.src = this.result as string;
                image.addEventListener('load', function () {
                    console.log(`height: ${this.height}, width: ${this.width}`);
                });
                        
            }, false);
                    
            reader.readAsDataURL(file);
        }
        

        基于Mozilla docs:

        readAsDataURL方法用于读取指定的内容 BlobFile。当读取操作完成时,readyState 变为DONE,触发loadend。当时result 属性包含作为数据的数据:表示文件的 URL 数据作为 base64 编码的字符串。

        browser compatibility 也在列表中。

        【讨论】:

          【解决方案6】:

          文件只是一个文件,你需要像这样创建一个图像:

          var _URL = window.URL || window.webkitURL;
          $("#file").change(function (e) {
              var file, img;
              if ((file = this.files[0])) {
                  img = new Image();
                  var objectUrl = _URL.createObjectURL(file);
                  img.onload = function () {
                      alert(this.width + " " + this.height);
                      _URL.revokeObjectURL(objectUrl);
                  };
                  img.src = objectUrl;
              }
          });
          

          演示:http://jsfiddle.net/4N6D9/1/

          我认为您意识到这仅在少数浏览器中受支持。主要是 firefox 和 chrome,现在也可能是 opera。

          P.S. URL.createObjectURL() 方法已从 MediaStream 接口 中删除。此方法已在 2013 年弃用,并通过将流分配给 HTMLMediaElement.srcObject 来取代。旧方法已被删除,因为它不太安全,需要调用 URL.revokeOjbectURL() 来结束流。其他用户代理已弃用 (Firefox) 或删除 (Safari) 此功能。

          更多信息请参考here

          【讨论】:

          • 除非您拥有 safari 6.0,否则它肯定无法在 safari 上运行。 6.0 是目前唯一支持文件 API 的版本。而且我认为苹果永远不会发布 Windows 6.0。 5.1.7 是很久以前 safari 的最新版本
          • 它在 IE10 中有效,但在 IE9 及更低版本中似乎无效。那是因为 IE9 及以下不支持 File API (caniuse.com/#search=file%20api)
          【解决方案7】:

              const ValidateImg = (file) =>{
                  let img = new Image()
                  img.src = window.URL.createObjectURL(file)
                  img.onload = () => {
                      if(img.width === 100 && img.height ===100){
                          alert("Correct size");
                          return true;
                      }
                      alert("Incorrect size");
                      return true;
                  }
              }

          【讨论】:

            【解决方案8】:

            这是检查大小的最简单方法

            let img = new Image()
            img.src = window.URL.createObjectURL(event.target.files[0])
            img.onload = () => {
               alert(img.width + " " + img.height);
            }
            

            检查具体尺寸。以 100 x 100 为例

            let img = new Image()
            img.src = window.URL.createObjectURL(event.target.files[0])
            img.onload = () => {
               if(img.width === 100 && img.height === 100){
                    alert(`Nice, image is the right size. It can be uploaded`)
                    // upload logic here
                    } else {
                    alert(`Sorry, this image doesn't look like the size we wanted. It's 
               ${img.width} x ${img.height} but we require 100 x 100 size image.`);
               }                
            }
            

            【讨论】:

              【解决方案9】:

              将函数附加到输入类型文件的onchange方法/onchange="validateimg(this)"/

                 function validateimg(ctrl) { 
                      var fileUpload = ctrl;
                      var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(.jpg|.png|.gif)$");
                      if (regex.test(fileUpload.value.toLowerCase())) {
                          if (typeof (fileUpload.files) != "undefined") {
                              var reader = new FileReader();
                              reader.readAsDataURL(fileUpload.files[0]);
                              reader.onload = function (e) {
                                  var image = new Image();
                                  image.src = e.target.result;
                                  image.onload = function () {
                                      var height = this.height;
                                      var width = this.width;
                                      if (height < 1100 || width < 750) {
                                          alert("At least you can upload a 1100*750 photo size.");
                                          return false;
                                      }else{
                                          alert("Uploaded image has valid Height and Width.");
                                          return true;
                                      }
                                  };
                              }
                          } else {
                              alert("This browser does not support HTML5.");
                              return false;
                          }
                      } else {
                          alert("Please select a valid Image file.");
                          return false;
                      }
                  }
              

              【讨论】:

                【解决方案10】:
                function uploadfile(ctrl) {
                    var validate = validateimg(ctrl);
                
                    if (validate) {
                        if (window.FormData !== undefined) {
                            ShowLoading();
                            var fileUpload = $(ctrl).get(0);
                            var files = fileUpload.files;
                
                
                            var fileData = new FormData();
                
                
                            for (var i = 0; i < files.length; i++) {
                                fileData.append(files[i].name, files[i]);
                            }
                
                
                            fileData.append('username', 'Wishes');
                
                            $.ajax({
                                url: 'UploadWishesFiles',
                                type: "POST",
                                contentType: false,
                                processData: false,
                                data: fileData,
                                success: function(result) {
                                    var id = $(ctrl).attr('id');
                                    $('#' + id.replace('txt', 'hdn')).val(result);
                
                                    $('#imgPictureEn').attr('src', '../Data/Wishes/' + result).show();
                
                                    HideLoading();
                                },
                                error: function(err) {
                                    alert(err.statusText);
                                    HideLoading();
                                }
                            });
                        } else {
                            alert("FormData is not supported.");
                        }
                
                    }
                

                【讨论】:

                • 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
                猜你喜欢
                • 2012-01-19
                • 2014-12-13
                • 1970-01-01
                • 2016-05-08
                • 1970-01-01
                • 1970-01-01
                • 2011-08-28
                • 2018-07-14
                • 2013-11-18
                相关资源
                最近更新 更多