ddvphp / ddv-file
ddv-file php library
Requires
- php: >=5.3
- aliyuncs/oss-sdk-php: ~2.0
- ddvphp/ddv-exception: 0.0.*
- paragonie/random_compat: ^2.0
Suggests
- paragonie/random_compat: Provides better randomness in PHP 5.x
This package is not auto-updated.
Last update: 2024-11-24 03:19:35 UTC
README
Installation - 安装
composer require ddvphp/ddv-file
- [客户端] 代指 IOS 安卓 Html5 flash
- [device_type] 目前允许
ios
android
html5
htmlswf
html4
wxmp
- 微信公众平台的浏览器一定要使用
wxmp
,不建议使用html5
- 否则会导致部分手机上传失败,因为微信浏览器的限制导致分块的计算公式不一样
一、客户端使用
1、获取分块大小
首先客户端[IOS 安卓 Html5 flash]获取文件大小, 调用一下接口,获取到分块大小以及总分块数
- ==服务户端计算规则==
- 定义
$part_size_min = 400*1024
;- 定义
$part_size_max = 15*1024*1024
;- 计算
$part_size = ceil(max($file_size/1000 , $part_size_min))
- 判断
$part_size
如果大于$part_size_max
抛出异常 暂时不能上传大于15G的文件- 计算
$part_sum = ceil($file_size/$part_size)
- 判断
$part_sum
如果大于1000
抛出异常 可以等于1000
暂时不能上传大于15G的文件因为我们的服务器目前设定最大接受上传15G 另外分块太大也给移动端带来压力
分块大小计算 是 取大原则
向上去整
- ==服务户端计算规则==
请求地址:v1_0/upload/filePartSize
使用说明:获取分块大小
需要登录:是
请求方法:GET
数据形式:x-www-form-urlencoded 、form-data
发送以下信息到服务器
样板数据
{ "fileSize" : "46650955", "fileType" : "audio/mp3", "deviceType" : "html5" }
返回结果
样板数据
"partSize" :"409600", "partSum" :114
2、获取文件id
- 前端读流方式计算文件的相关信息
- 以partSize的大小进行流式读取文件
- 计算文件的总内容的md5为fileMd5
- 计算文件的总内容的sha1为fileSha1
- 计算文件的总内容的crc32为fileCrc32
- 计算当前每一块的流的二进制的md5的hex值 并且拼接为partMd5Str
- 比如第一块的md5是 0fdf5be93cd24aeeaccb046406c3a643
- 比如第二块的md5是 986f5be93cd24ae9accb047776c3a332
- 比如第三块的md5是 85658be93cd24aeeaccb046406c3a757
- 使用partMd5Str = partMd5Str + {上一块md5}
- 那么partMd5Str是0fdf5be93cd24aeeaccb046406c3a643986f5be93cd24ae9accb047776c3a33285658be93cd24aeeaccb046406c3a757
- partMd5Str随着分块累计不停变长,但是不会超过 1000*32=32000字节
- 最后 得到 md5、sha1、crc32
- 还有 filePartMd5Lower = md5(partMd5Str[转小写]) + '-' + partSum
- 还有 filePartMd5Upper = md5(partMd5Str[转大写]) + '-' + partSum
- 得到 filePartMd5Lower为4CF26963D7C141DEFBC985382538B43F-3
- 得到 filePartMd5Upper为BB49107DFF0A0054DC67D94B1FFC5A24-3
请求地址:v1_0/upload/fileId
使用说明:获取分块大小
需要登录:是
请求方法:GET
数据形式:x-www-form-urlencoded 、form-data
发送以下信息到服务器
样板数据
"fileCrc32" :"5434bd00", "fileMd5" :"0fdf5be93cd24aeeaccb046406c3a643", "fileSha1" :"4b0e042ee37cc8947bd6e4a5ef6bbc53a85ba7f9", "filePartMd5Lower" :"4CF26963D7C141DEFBC985382538B43F-3", "filePartMd5Upper" :"BB49107DFF0A0054DC67D94B1FFC5A24-3", "fileName" :"1.mp3", "fileSize" :"46650955", "fileType" :"audio/mp3", "lastModified" :"1449682232.043", "manageType" :"admin", "directory" :"common/other", "deviceType" :"html5"
返回结果
样板数据
"fileId" :"1", "fileCrc32" :"5434bd00", "fileMd5" :"0fdf5be93cd24aeeaccb046406c3a643", "fileSha1" :"4b0e042ee37cc8947bd6e4a5ef6bbc53a85ba7f9", "path" :"/fafssdf/df/as/fas/s.jpg", "url" :"http://www.xxxx.x.com/fafssdf/df/as/fas/s.jpg", "isUploadEnd" :false
如果
isUploadEnd
已经成功上传就跳过下列所有步骤
3、获取成功上传的信息
请求地址:v1_0/upload/filePartInfo
使用说明:获取成功上传的信息
需要登录:是
请求方法:GET
数据形式:x-www-form-urlencoded 、form-data
发送以下信息到服务器
样板数据
"fileId" :"1", "fileCrc32" :"5434bd00", "fileMd5" :"0fdf5be93cd24aeeaccb046406c3a643", "fileSha1" :"4b0e042ee37cc8947bd6e4a5ef6bbc53a85ba7f9"
服务器返回
样板数据
"fileSize" :"46650955", "partSize" :"46651", "partSum" :1000, "doneParts" :[1,3,6,8], "isUploadEnd" :false
客户端从1
开始循环到{partSum}
切块 执行4、获取分块签名
的步骤 跳过doneParts
的成功上传块
服务在这个时候建立uploadid 并且查询成功上传的块信息 如果是第一次产生的uploadid 块信息doneParts为空数组 如果有uploadid就查询阿里云或者百度云的done_parts信息
注意 如果
isUploadEnd
已经成功上传就跳过下列所有步骤
4、获取分块签名
请求地址:v1_0/upload/filePartMd5
使用说明:获取成功上传的信息
需要登录:是
请求方法:GET
数据形式:x-www-form-urlencoded 、form-data
发送以下信息到服务器
样板数据
"fileId" :"1", "fileCrc32" :"5434bd00", "fileMd5" :"0fdf5be93cd24aeeaccb046406c3a643", "fileSha1" :"4b0e042ee37cc8947bd6e4a5ef6bbc53a85ba7f9", "partNumber" :"1", "partLength" :"30", "md5Base64" :"MDE1Mjg4ZDViMGFmZjBiYzExOTQ0NDhlODFmZDU1NTQ=", "deviceType" :"html5"
服务器返回
样板数据
{ "data":{ "url":"http://xxxx.x.x.x.x.x.x/caomdsfas/fda/dfa/dsa", "method":"PUT", "headers":{ "Content-Type":"application/octet-stream", "Content-Md5":"MDE1Mjg4ZDViMGFmZjBiYzExOTQ0NDhlODFmZDU1NTQ=" }, "headers_array":[ ["Content-Type","application/octet-stream"], ["Content-Md5","MDE1Mjg4ZDViMGFmZjBiYzExOTQ0NDhlODFmZDU1NTQ="] ] } }
因为头的key的特殊性 传参可以带
isHeaderArray
=true
来得到数组头
5、获取成功上传的信息
请求地址:v1_0/upload/complete
使用说明:获取成功上传的信息
需要登录:是
请求方法:POST
数据形式:x-www-form-urlencoded 、form-data
发送以下信息到服务器
样板数据
{ "fileId" :"1", "fileCrc32" :"5434bd00", "fileMd5" :"0fdf5be93cd24aeeaccb046406c3a643", "fileSha1" :"4b0e042ee37cc8947bd6e4a5ef6bbc53a85ba7f9" }
服务器返回有 空数组代表成功,如果抛出异常就看一下是否为漏切片
二、服务器使用
我们以
laravel
框架为样本使用
我们以laravel提供一个样本
==服务户端计算规则== 定义
$partSizeMin = 400*1024
; 定义$partSizeMax = 15*1024*1024
; 计算$partSize = ceil(min(fileSize,max(ceil(fileSize/$partSumMax),$partSizeMin)))
判断$partSize
如果大于$partSizeMax
抛出异常 暂时不能上传大于15G的文件 计算$partSum = ceil($fileSize/$partSize)
判断$partSum
如果大于1000
抛出异常 可以等于1000
暂时不能上传大于15G的文件因为我们的服务器目前设定最大接受上传15G 另外分块太大也给移动端带来压力
分块大小计算 是 取大原则
向上去整
==服务户端计算规则==
1、路由初配置
Route::group(['prefix'=>'upload'],function(){ Route::get('filePartSize','Api\UploadController@filePartSize'); Route::get('fileId','Api\UploadController@fileId'); Route::get('filePartInfo','Api\UploadController@filePartInfo'); Route::get('filePartMd5','Api\UploadController@filePartMd5'); Route::post('complete','Api\UploadController@complete'); });
2、控制器文件Api\UploadController
2.1、 配置初始化
public function __construct(){ method_exists(parent::class, '__construct') && parent::__construct(); $this->fileConfigInit(); } private function fileConfigInit (){ // 基本配置 $config = [ // uid 可以为null和字符串0 // uid 如果为null 每次获取fileId都会拿到新的id,因为每个文件不确定是那个用户的 // uid 如果为0 ,插件支持0这个uid,没有登录的用户统一视为0这个用户的 'uid'=>'0' // fileIndex 是一个可选参数,如果配置了,会导致文件系统返回的地址通通是索引地址哦 // fileIndex 是一个索引标识 'fileIndex'=>'videolive', // 默认不属于uid标识索引文件 'fileIndexUseUid'=>false, // 默认一块最小字节数 'partSizeMin'=>400*1024, // 默认一块最大字节数 'partSizeMax'=>15*1024*1024, // 默认一共可以多少块 'partSumMax'=>1000 ]; // 使用存储驱动,比如阿里云的驱动,也可以pr扩展驱动[感谢] $drivers = new \DdvPhp\DdvFile\Drivers\AliyunOssDrivers(config('aliyun.oss')); // 数据库模型,目前提供laravel数据模型,也可以pr数据模型[感谢] $database = new \DdvPhp\DdvFile\Database\LaravelMysqlDatabase(); // 实例化文件类 $this->upload = new \DdvPhp\DdvFile($config, $drivers, $database); }
2.2、获取分块大小 接口
## 获取分块大小 public function filePartSize (Request $request){ return [ 'data' => $this->upload->getPartSize($request->only(['fileSize','fileType','deviceType'])) ]; }
2.3、获取文件id 接口
## 获取文件id public function fileId(Request $request){ $input = $request->only( $this->upload->getFileIdInputKeys([ // 授权类型 'authType', // 管理类型 'manageType', // 上传目录 'directory' ]) ); // 自己的业务逻辑,和权限逻辑 return [ 'data' => $this->upload->getFileId($input) ]; }
2.3、获取成功上传的信息
## 获取成功上传的信息 public function filePartInfo(Request $request){ $input = $request->only( [ 'fileId', 'fileMd5', 'fileSha1', 'fileCrc32' ] ); return [ 'data' => $this->upload->getFilePartInfo($input) ]; }
2.4、获取分块签名
## 获取分块签名 public function filePartMd5 (Request $request){ $input = $request->only( [ 'fileId', 'fileMd5', 'fileSha1', 'fileCrc32', 'contentMd5', 'partLength', 'partNumber' ] ); return [ 'data' => $this->upload->getFilePartMd5($input) ]; }
2.5、合并上传文件
## 合并上传文件 public function complete(Request $request){ $input = $request->only( [ 'fileId', 'fileMd5', 'fileSha1', 'fileCrc32' ] ); return [ 'data' => $this->upload->complete($input) ]; }