图集1/3

正文 1179字数 319,367阅读

从服务器加载图片,如果要等图片加载完后才获取到大小那就麻烦了。能不能在图片加载完成之前就获取到它的大小呢?当然可以,图片文件的大小是保存在图片的文件头中的,后面的是数据部分。我们用16进制工具打开一张图片就很容易看出。

我选中的部分就是图片的大小信息,只要一个图的头部被加载完成,就可以获取到它的大小。我们来做一个实验,写一个服务器程序,先输出一个图片的头部,等待一秒以后再输出图片的全部。下面是PHP代码
//MyPicture.php //先输出一个图片的HTTP头 header('Content-type: image/png'); //从文件中加载图片数据 $data=file_get_contents('signet.png'); //设置一个分段大小 $mid=0x30; //输出文件的前$mid字节 echo substr($data,0,$mid); //把输出的数据发送到客户端 flush(); //等待1秒 sleep(1); //从$mid位置开始输出图片的剩余数据 echo substr($data,$mid);
Run code
Cut to clipboard

    这个MyPicture.php就是我们的图片地址了,直接访问它会先卡住一秒然后刷出图片。

    接着我们要写客户端JavaScript代码向服务器请求这张图片,趁服务器在sleep的时候偷偷的把图片大小取到。
    //创建一个图片对象 var img=new Image; //图片加载完成事件 img.onload=function(){ console.log("onload",img.width,img.height); }; //发送请求 //URL上加随机数避免缓存影响结果 img.src="MyPicture.php?"+Math.random(); //设置0.5秒以后输出图片大小 //我猜0.5秒这点时间足够图片头部加载完成了 setTimeout(function(){ console.log("setTimeout",img.width,img.height); },500);
    Run code
    Cut to clipboard


      看呐,setTimeout执行的时候我们就已经获取到图片大小了。这就可以证明一张图片只需要加载3*16字节或者更少就可以得到图片大小了。如果你想在项目中使用这个手法当然可以,但是像上面的代码那样写了。本地测试的时候这样写还行,真正使用的时候因为有些用户的网络环境很奇葩,我们完全无法估计0.5秒能不能加载到图片的头部,所以建议使用setInterval或递归setTimeout去取,取到或者错误了再结束。