1.首先引入华为云php-sdk
https://github.com/huaweicloud/huaweicloud-sdk-php-obs.git
2.进入目录执行composer install
3.先引入obsautoload.php
use Obs\ObsClient;
$this->obsClient = new ObsClient([
'key' => "ak",
'secret' => "sk",
'endpoint' => "endpoint",
'ssl_verify' => false,
'chunk_size' => 1*1024*1024
]);
public function upload(array $data){
extract($data);
$content = file_get_contents($file);
$part_num = $data['part_num'] ?? 1;
$total_part = $data['total_part'] ?? 1;
list($file_dir, $ext) = explode('/', $type);
$file_dir = $file_dir . '/' . date("Ymd");
// $upload_dir = config('upload_dir') . '/' . $file_dir;
$unique_flag = $data['unique_flag'] ?? '';
if(!$unique_flag){
return $this->outPut(ErrorCode::UPLOAD_FAIL);
}
$file_name = $file_dir . '/' . $unique_flag . '.' . $ext;
$uploadId = "";
$r1 = $this->obsClient->listMultipartUploads ( [
'Bucket' => 'xfw20200520'
]);
foreach ($r1['Uploads'] as $k => $v ) {
var_dump($v["Key"]);
if($v["Key"] == $file_name){
$uploadId = $v["UploadId"];
}
}
if(!$uploadId){
//初始化多段上传对象
$parameter["Bucket"] = "xfw20200520";
$parameter["Key"] = $file_name;
$parameter["ContentType"] = $type;
$resp = $this->obsClient->initiateMultipartUpload($parameter);
$uploadId = $resp['UploadId'];
}
//切片上传
$upload_res = $this->obsClient->uploadPart([
'Bucket' => "*",
'Key' => $file_name,
// 设置分段号,范围是1~10000
'PartNumber' => $part_num,
// 设置Upload ID
'UploadId' => $uploadId,
'Body' => $content,
// 设置将要上传的大文件,localfile为上传的本地文件路径,需要指定到具体的文件名
// 'SourceFile' => $file,
// 设置分段大小
'PartSize' => $size,
// 设置分段的起始偏移大小
'Offset' => $size*($part_num-1)
]);
if($upload_res["HttpStatusCode"] != 200){
//取消分片上传
$del_res = $this->obsClient->abortMultipartUpload([
'Bucket' => "*",
'Key' => $file_name,
// 设置Upload ID
'UploadId' => $uploadId
]);
return $this->outPut(ErrorCode::UPLOAD_FAIL);
}
//查询已上传列表
$res = $this->obsClient->listParts([
'Bucket' => "*",
'Key' => $file_name,
// 设置Upload ID
'UploadId' => $uploadId,
]);
var_dump(count($res["Parts"]));
var_dump($total_part);
if(count($res["Parts"]) == $total_part){
$parts = [];
foreach($res["Parts"] as $k => $v){
$parts[$k]["PartNumber"] = $v["PartNumber"];
$parts[$k]["ETag"] = $v["ETag"];
}
$all_name = Helper::createGuid() . '.' . $ext;
$all_name = $file_dir . '/' . $all_name;
//合并文件
$get_res = $this->obsClient->completeMultipartUpload([
'Bucket' => "***",
'Key' => $file_name,
// 设置Upload ID
'UploadId' => $uploadId,
'Parts' => $parts
]);
if($get_res["HttpStatusCode"] == 200){
$return_info['file_name'] = "*****" . '/' . $file_name;//自定义文件名
$return_info = Helper::selfData($return_info);
return $this->outPut(ErrorCode::SUCCESS, false, $return_info);
}else{
return $this->outPut(ErrorCode::UPLOAD_FAIL);
}
}
return $this->outPut(ErrorCode::SUCCESS);
}
4注意问题
1。如果上传的是临时路径最好读过之后再把内容给华为云,因为我就遇到过切片后面的片临时路径失效,读不到文件内容
进程抛出信号signal=11,导致worker挂掉
2.只创建一次初始化对象,所以创建之前先查询看有没有这个文件的对象,key是华为云路径+文件名,只能查出所有对象后循环对比
没有条件直接查有没有这个对象
3.严格控制上传规则,建议先传一片再开多线程随便传,因为可能在你初始化对象还没创建好的时候,你的查询判断已经执行完毕,所以一定要确保初始化对象先创建,查询对象再查询
4.切片全部上传之后,跟华为云查询片数是否完整。完整的话合并,无论哪个切片上传失败记得跑取消初始化任务的接口,不然会造成你的碎片泛滥
5.本文代码使用php Hyperf框架。目前发现很少有人写,所以大家可以看下。这样的上传效率十分的高。