Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javascript 上传图片 检测宽度 高度 文件大小 #11

Open
purplebamboo opened this issue Jul 11, 2017 · 0 comments
Open

javascript 上传图片 检测宽度 高度 文件大小 #11

purplebamboo opened this issue Jul 11, 2017 · 0 comments

Comments

@purplebamboo
Copy link
Owner

javascript 上传图片 检测宽度 高度 文件大小

最近做一个iframe上传的组件,需要限制上传文件的 高度宽度还有 大小。所以研究了下如何使用js获取这些信息。
网上的内容很多,不过很多解决方案都是有问题,下面进行些罗列和分析。
网上的几种解决方案

##第一种:

var image1 = new Image();
image1.dynsrc = path;
alert(image1.dynsrc);  //这里路径显示真确
alert(image1.fileSize);  //但是这里老是-1 为什么??

老是-1 是因为没有加载完,所以需要onload判断
dynsrc只有ie支持,但是连ie自己都给放弃了,经测试只有ie6支持。7,8都不行。
应该使用src属性。

var image = new Image();
image.onload =function(){
    var width = image.width;
    var height = image.height;
    var fileSize = image.fileSize;
    //alert(width+'======'+height+"====="+fileSize);
}
image.src = path;

改成这个后,测试 ie系列都支持,但是 在chrome等现代浏览器下是不行的,chrome这些浏览器 不允许读取本地的文件。
这边需要注意的是:最好将onload函数放在image.src = path 的前面,因为image对象下次加载时会优先读取缓存,onload放在后面可能会造成加载太快,来不及触发onload事件。

##第二种:

function getFileSize(filePath)     
{     
    var fso = new ActiveXObject("Scripting.FileSystemObject");     
    alert("文件大小为:"+fso.GetFile(filePath).size);     
}    

没有测试 基本没有意义,会弹出安全提示
这种方法可以实现,也容易被开发人员想到,但是需要更改浏览器的安全设置,不然会报“Automation服务器不能创建对象”这个脚本错误。将浏览器的安全设置改为“中”,然后将ActiveX的设置设为启用就OK了,显然不能对用户做出什么要求,所以不推荐。

##第三种:
使用html5的 http://caniuse.com/fileapi

    var f = document.getElementById("file").files[0];
    var reader = new FileReader();
    reader.onload = function (e) {
        var data = e.target.result;
        //加载图片获取图片真实宽度和高度
        var image = new Image();
        image.onload=function(){
            var width = image.width;
            var height = image.height;
            alert(width+'======'+height+"====="+f.size);
        };
        image.src= data;
   };
   reader.readAsDataURL(f);

这是使用的html5技术,测试大部分现代浏览器都是可行的。

##第四种
经过查看开源组件的源码,发现了一种独特的写法,通过ie的滤镜实现读取文件的宽度高度

var input = self.input[0]
var temp_document = self.iframe[0].contentDocument || self.iframe[0].document;
input.select();
//确保IE9下,不会出现因为安全问题导致无法访问
input.blur();
var src = temp_document.selection.createRange().text;
var img = $('<img style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=image);width:300px;visibility:hidden;"  />').appendTo('body').getDOMNode();
img.filters.item('DXImageTransform.Microsoft.AlphaImageLoader').src = src;
var width = img.offsetWidth;
var height = img.offsetHeight;
$(img).remove();

此代码需要jquery选择器的支持。这种方法据说最稳定。

通过以上的分析,确定出一种最稳妥的跨浏览器的解决方案为

window.check=function(){
var input = document.getElementById("file");
if(input.files){
                //读取图片数据
  var f = input.files[0];
  var reader = new FileReader();
  reader.onload = function (e) {
      var data = e.target.result;
      //加载图片获取图片真实宽度和高度
      var image = new Image();
      image.onload=function(){
          var width = image.width;
          var height = image.height;
          alert(width+'======'+height+"====="+f.size);
      };
      image.src= data;
  };
  reader.readAsDataURL(f);
  }else{
  var image = new Image(); 
  image.onload =function(){
      var width = image.width;
      var height = image.height;
      var fileSize = image.fileSize;
      alert(width+'======'+height+"====="+fileSize);
  }
  image.src = input.value;

  }

}

对应的html为:

<input id="file" type="file">
<input id="Button1" type="button" value="button" onclick="check()">

ps:
这个地址http://www.planeart.cn/?p=1121 使用一种方式可以很方便的提前获取 width和height 非常好
思路是,浏览器在图片未加载完时会通过http协议的header提前知道width和height,所以通过一个计时器,不停检测,快速的得到宽度高度。

代码如下:

// 更新:
// 05.27: 1、保证回调执行顺序:error > ready > load;2、回调函数this指向img本身
// 04-02: 1、增加图片完全加载后的回调 2、提高性能

/**
 * 图片头数据加载就绪事件 - 更快获取图片尺寸
 * @version 2011.05.27
 * @author  TangBin
 * @see   http://www.planeart.cn/?p=1121
 * @param {String}  图片路径
 * @param {Function}  尺寸就绪
 * @param {Function}  加载完毕 (可选)
 * @param {Function}  加载错误 (可选)
 * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
    alert('size ready: width=' + this.width + '; height=' + this.height);
  });
 */
var imgReady = (function () {
  var list = [], intervalId = null,

  // 用来执行队列
  tick = function () {
    var i = 0;
    for (; i < list.length; i++) {
      list[i].end ? list.splice(i--, 1) : list[i]();
    };
    !list.length && stop();
  },

  // 停止所有定时器队列
  stop = function () {
    clearInterval(intervalId);
    intervalId = null;
  };

  return function (url, ready, load, error) {
    var onready, width, height, newWidth, newHeight,
      img = new Image();
    
    img.src = url;

    // 如果图片被缓存,则直接返回缓存数据
    if (img.complete) {
      ready.call(img);
      load && load.call(img);
      return;
    };
    
    width = img.width;
    height = img.height;
    
    // 加载错误后的事件
    img.onerror = function () {
      error && error.call(img);
      onready.end = true;
      img = img.onload = img.onerror = null;
    };
    
    // 图片尺寸就绪
    onready = function () {
      newWidth = img.width;
      newHeight = img.height;
      if (newWidth !== width || newHeight !== height ||
        // 如果图片已经在其他地方加载可使用面积检测
        newWidth * newHeight > 1024
      ) {
        ready.call(img);
        onready.end = true;
      };
    };
    onready();
    
    // 完全加载完毕的事件
    img.onload = function () {
      // onload在定时器时间差范围内可能比onready快
      // 这里进行检查并保证onready优先执行
      !onready.end && onready();
    
      load && load.call(img);
      
      // IE gif动画会循环执行onload,置空onload即可
      img = img.onload = img.onerror = null;
    };

    // 加入队列中定期执行
    if (!onready.end) {
      list.push(onready);
      // 无论何时只允许出现一个定时器,减少浏览器性能损耗
      if (intervalId === null) intervalId = setInterval(tick, 40);
    };
  };
})();


调用例子

imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
  alert('size ready: width=' + this.width + '; height=' + this.height);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant