之前做了一个大文件的分片上传,做好之后就没管了,让客户端一直自己用着,然后期间偶尔会有浏览器不兼容的现象我也懒得改,然后十一回来,客户端就给我说,有文件上传不上去,然后正好手头没活,就用改了下
先看下思路,这里做了分片上传,就是文件按照一小块一小块分片上传到服务器后,然后拼接,拉到七牛
拉到七牛的代码如下
/* * 上传到七牛 */ public static function saveQiniuByUrl($file_url){ $data = file_get_contents($file_url); //七牛的密钥、域名和空间 $access_key = Yii::$app->params['access_key']; $secret_key = Yii::$app->params['secret_key']; $bucket = Yii::$app->params['bucket']; //上传7牛的文件的名字及路径 $file_name = basename($file_url); //授权 $auth = new Auth($access_key,$secret_key); //生成token $token = $auth->uploadToken($bucket); $uploadManager = new UploadManager(); list($ret,$err) = $uploadManager->put($token,$file_name,$data); if($err !== null){ return false; } return Yii::$app->params['domain'].'/'.$file_name; }
我只需要提供本地的组装好的文件的位置就可以
然后我打印了下七牛的返回
array (size=2) 0 => null 1 => object(Qiniu\Http\Error)[89] private 'url' => string 'http://up.qiniup.com' (length=20) private 'response' => object(Qiniu\Http\Response)[88] public 'statusCode' => int 614 public 'headers' => array (size=16) ... public 'body' => string '{"error":"file exists"}' (length=23) public 'error' => string 'file exists' (length=11) private 'jsonData' => array (size=1) ... public 'duration' => float 12.178
关键的一句话,file exists
查了七牛的文档,我知道了原因,七牛判断文件是否相同是根据文件的key,即文件的名字,我上传文件到服务器后,保留了上传之前的名称,所以会出现这个问题,那我们如何避免用户上传相同key的文件呢?
七牛已经提供好了相应的算法,见 https://github.com/qiniu/qetag
算法大体如下:
如果你能够确认文件 <= 4M,那么
hash = UrlsafeBase64([0x16, sha1(FileContent)])
如果文件 > 4M,则
hash = UrlsafeBase64([0x96, sha1([sha1(Block1), sha1(Block2), ...])])
其中 Block 是把文件内容切分为 4M 为单位的一个个块,也就是
BlockI = FileContent[I*4M:(I+1)*4M]
上传到七牛云存储的时候,key 是可选的。如果你不指定 key,则自动以 hash 值作为 key,此时自动带了消重能力。两个用户上传相同的文件,最终的 key 是一样的。
另外需要指出,当上传相同的文件时,七牛不会覆盖,只能你手动删除某个文件然后才能上传相同文件(如果你想覆盖的话)
我这里的解决就比较简单了,直接生成唯一的key拼接下就可以了