/hanziyun-FileSever

hanziyun file sever processing program development by CodeIgniter framework

Primary LanguagePHP

☁️汉子云文件上传文件服务端程序

hanziyun file sever processing program development by CodeIgniter framework 基于PHP CI框架🇨🇳

🌀简介

旨在于解决中小企业应用的文件传输问题:trollface:

😃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方法输入文件
  * @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;
		}
	}

第五步:

完成上传

The Future:

支持类似阿里云的自定义输出格式

百度编辑器的图片上传的最大化支持