H5应用必须掌握的技能点-图片篇
http://www.imwinlion.com/archives/158
1、怎么存储图片
这个问题的实质是如何设计上节 的$dstPath问题。是为什么会有这个问题呢?笔者在日常开发种发现很多图片存储无设计, 所以的到的图片大概是这样的
http://shang.qq.com/wpa/qunwpa?idkey=7322d7b39a8564d24b48b5e7d83fcde645f4c0e9ad84f1f7ddc7baff47574d7d
http://www.imwinlion.com/wp-content/uploads/2016/04/新建图像-300×300.png
像这种图片结构,在应用根目录下新建一个upload 文件夹,然后下面分日期/uploads/2016/04/ 在小型的应用中,还能将就着用的,但是一旦图片数目多起来,并且要存储的是图片的id时,我们该怎么做呢?笔者研读阿里的 fastfs,并经过大量的应用实践,积累了一套实用好操作的图片命名策略,如下
[hostid][level][dirstr][filename][suffix]
这种名称策略怎么理解呢?
hostid:图片服务器资源ID.这个涉及到我们自身的服务器资源规划问题。自定义的,比如我们应用占用了俩台服务器资源,一台是应用服务器,我们编号为0,一台是资源服务器,我们将这个服务器资源编号为1,这个数据就是hostid
level:相对于图片服务根目录来说,图片存储的文件夹目录深度,一般为俩层。比如我们存储的根目录为 /mnt/h5app/,那么这下面 的 目录 a/b/c,level就是3
dirstr:目录字符串,如上,目录字符串就是abc
filename: md5 策略或者uuid 策略生成 的文件名,如md5(microtime() . mt_rand(1000,9999));
suffix:文件的后缀,如.jpg,.png
举个列子。假设我们的应用服务器服务器,编号是0,根目录是/alidata/www/www.imwinlion.com/ ,对应的域名是www.imwinlion.com
我们的图片服务器有三台,一台编号是1,目录是/mnt/www.imwinlion.com/ ,对应的域名是res1.imwinlion.com
另一台编号是2,根目录是/mnt/www.imwinlion.cn/,对应的域名是res2.imwinlion.com
现在,我们根据我们设计的文件存储策略,假设名称是13abc01f9c76ce5c45aeec2e6f816c95b854b.jpg,那么根据问价夹的第1位数字,知道这个文件hostid 是1,
应该存放在编号为1的服务器,也就是/mnt/www.imwinlion.com/ 下
根据第二个参数level 为3,我们知道这个文件有3个父级子目录,那么接下来的三个字母abc 就是dirstr , 接下来的01f9c76ce5c45aeec2e6f816c95b854b 是md5 生成的随机字符串
最后.jpg 是文件格式,那么这个文件的存储路径应该是这样
/mnt/www.imwinlion.com/a/b/c/13abc01f9c76ce5c45aeec2e6f816c95b854b.jpg
对应访问地址是这样 http://res1.imwinlion.com/a/b/c/13abc01f9c76ce5c45aeec2e6f816c95b854b.jpg,文件id 就是文件名称 13abc01f9c76ce5c45aeec2e6f816c95b854b.jpg
我们数据库存这个id ,前端只要根据策略和这个ID就能够获得 图片路径
这种策略的核心在于先根据业务逻辑规划出图片存放路径。是先知道了文件路径,然后再存储。但是我们常用的框架,把文件的命名策略封闭起来了,我们只能先存起来,再获得文件名。这需要改造!!
2、给个实例
此列子相关的详细场景 见
http://www.imwinlion.com/archives/158
<?php //cfgupload.php 配置文件
return array (
'UPLOAD' =>
array (
'maxSize' => 2097152,
'exts' =>
array (
0 => 'jpg',
1 => 'gif',
2 => 'png',
3 => 'jpeg',
4=>"mp3",
),
'rootPath' => '/mnt/img.imwinlion.com/',
'savePath' => '',
'driver' => 'Local',
'subType' => 'hash',
'hashLevel' => 1,
'domain' => 'res1.imwinlion.com',
'scheme' => 'http',
'subDir' => 'upload',
),
);
/*该函数处理前端上传过来的base64场景*/
function uploadb64(){
$uploadcfg=C('UPLOAD');
$hashLevel = intval($uploadcfg["hashLevel"]);
$rootPath = $uploadcfg["rootPath"];
$savePath = $uploadcfg["savePath"];
$subDir = $uploadcfg["subDir"];
$scheme = $uploadcfg["scheme"];
$domain = $uploadcfg["domain"];
$dir = "";
$filename = md5(microtime()).".jpg";
$str = "0123456789abcdef";
$a1 = "";
$a2 = "";
if($hashLevel!=2 && $hashLevel!=1){
$$hashLevel = 1;
}
if($hashLevel==1){
$a1 = $str[mt_rand(0,strlen($str))];
$savePath = $a1;
$filename = $hashLevel. $a1 .$a2. $filename;
}
if($hashLevel==2){
$a1 = $str[mt_rand(0,strlen($str))];
$a2 = $str[mt_rand(0,strlen($str))];
$savePath = $a1 ."/" .$a2 ;
$filename = $hashLevel . $a1 .$a2. $filename;
}
//根据策略获得hostid
$filename .= ($this->gethostid(0) . $filename);
$this->base64toimage($this->request["data"],$rootPath . "/" . $subDir ."/". $savePath ."/". $filename );
$resp = array();
$url = $scheme. "://" . $domain . "/". $subDir ."/".$savePath ."/". $filename ;
$resp["url"] = $url;
$resp["error"] = 0;
$resp["state"]="SUCCESS";
if($this->request["callback"]) {
echo '<script>'.$callback.'('.json_encode($resp).')</script>';
} else {
echo json_encode($resp);
}
}
function base64toimage($strBase64, $outputFile ) {
$ifp = fopen( $outputFile, "wb" );
fwrite( $ifp, base64_decode( $strBase64) );
fclose( $ifp );
return( $outputFile );
}
/*这里有个技巧,我们根据入参业务频繁程度获取if*/
function gethostid($type=0){
//存那一台服务器逻辑需要我们自己编写
//我们这里演示 默认定死了 为1
return 1;
} 最佳答案