☁️ 汉子云文件上传文件服务端程序
hanziyun file sever processing program development by CodeIgniter framework 基于PHP CI框架
🌀 简介
😃 FileServer为文件服务器端(即接受并存储文件的服务器),部署此程序在服务器即可
🌀 使用
- 推荐部署在Linux服务器上
- 设置必要参数
在下面路径Controller文件中
> phpfile\application\controllers\Stream.php
❗ 必须设置项:$upload_host 为上传处理服务器域名,$allow_origin为允许跨域的CDN域名数组
//上传处理服务器的host
public static $upload_host = 'http://upload.xxxxx.com/';
//允许跨域的origin列表
public static $allow_origin = array(
'http://cdn.xxxxx.com',
);
‼️ 在服务器上将file,upload文件夹权限设置为777
- file文件夹存储文件
- upload文件夹存储临时上传文件(分块数据)
🌀 原理
第一步:
- 通过PUT方法CDN将文件传输至此服务器,将先验证签名方法*__verifySignature()*
- 此签名方法见下图
🔗 详细签名认证字符串方法点此链接
第二步:
通过读流的方式存储文件数据
/**
* PUT方法输入文件
* @author: Ethen <553299576@qq.com>
* @DateTime 2016-09-08T20:51:22+0800
* @return [type] [description]
*/
private function __filePUT(){
//生成文件,读流
$partNumber = $this->input->get('partNumber');
$uploadId = $this->input->get('uploadId');
$bucket = $this->input->get('bucket');
$access_key_id = $this->input->get('access_key_id');
$access_key_secret = $this->input->get('access_key_secret');
//验证签名
$verify = $this->__verifySignature($bucket,$access_key_id,$access_key_secret);
if ($verify == false) {
var_dump('签名错误');die();
}
$path = $this->uri->uri_string();
//var_dump($path);
//获取内容的分界
$input = fopen('php://input', 'rb');
$url = __ROOT_PATH__.'upload/'.$uploadId.'/'.$partNumber.'.temp';
if ($this->dirExists(dirname($url))) {
$file_handle = fopen($url, 'wb');
//初始化增量Md5运算上下文
$md5_ctx = hash_init('md5');
while( ( $chunk = self::__fgets( $input, null , $md5_ctx ) ) !== false ){
if( fwrite( $file_handle, $chunk ) === false ){
var_dump('错误');
break;
}
}
//关闭输入流
fclose( $input );
fclose( $file_handle );
//获取二进制的md5
$data_md5_raw = hash_final($md5_ctx,true);
$data_md5 = base64_encode($data_md5_raw);
//匹配MD5
$filesize = filesize($url);
$cearte_part = $this->__filePart($uploadId,$partNumber,$data_md5,$filesize,$bucket);
if ($cearte_part == false) {
var_dump('错误');
//break;
return;
}
//释放内存
unset($md5_ctx);
}
return;
}
/**
* 设定指针读流
* @author: Ethen <553299576@qq.com>
* @DateTime 2016-09-08T20:56:03+0800
* @param [type] $handle [指针]
* @param [type] $length [长度]
* @param [type] $ctx [MD5上下文(增量)]
* @return [type] [description]
*/
private static function __fgets ( $handle , $length =null , $ctx = null ){
$r = '';
if (is_null($length)) {
$r = fgets($handle);
}else{
$r = fgets($handle,$length);
}
//增量 哈希 运算
if (!is_null($ctx)) {
hash_update($ctx, $r);
}
//返回
return $r;
}
第三步:
分片数据将先以*.temp*的格式存储,待所有分片传完将会合并存至指定路径保存(支持续传)
第四步:
告知上传upload服务器已传完,删除分块表中的数据
/**
* 分块文件的处理
* @author: Ethen <553299576@qq.com>
* @DateTime 2016-09-08T20:57:49+0800
* @param [type] $uploadId [description]
* @param [type] $partNumber [description]
* @param [type] $data_md5 [description]
* @param [type] $filesize [description]
* @param [type] $bucket [description]
* @return [type] [description]
*/
private function __filePart($uploadId,$partNumber,$data_md5,$filesize,$bucket){
$param = array(
'uploadId' => $uploadId,
'partNumber' => $partNumber,
'eTag' => $data_md5,
'lastModified' => date('Y-m-d H:i:s',time()),
'size' => $filesize,
'bucket' => $bucket
);
$this->load->helper('common');
$content = http_post(self::$upload_host.'v1_0/api/upload_part',$param);
$data = json_decode($content);
$data = object_array($data);
if ($data['code'] == 200) {
return true;
}else{
return false;
}
}