hyperf-chat/app/Service/SplitUploadService.php

164 lines
5.4 KiB
PHP
Raw Normal View History

2020-11-21 19:53:01 +08:00
<?php
2021-09-11 12:41:28 +08:00
declare(strict_types=1);
2020-11-21 19:53:01 +08:00
namespace App\Service;
2022-01-22 20:08:19 +08:00
use App\Constant\FileDriveConstant;
2022-01-19 22:02:00 +08:00
use App\Model\SplitUpload;
2020-11-21 19:53:01 +08:00
use Hyperf\HttpMessage\Upload\UploadedFile;
2021-06-30 19:27:49 +08:00
use League\Flysystem\Filesystem;
2020-11-21 19:53:01 +08:00
/**
* 文件拆分上传服务
*
* @package App\Service
*/
class SplitUploadService
{
2020-12-02 17:15:32 +08:00
/**
* 文件拆分的大小
*/
2020-11-21 19:53:01 +08:00
const SPLIT_SIZE = 2 * 1024 * 1024;
/**
* 创建文件拆分相关信息
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2022-01-19 22:02:00 +08:00
* @param string $fileName 文件名
* @param int $fileSize 文件大小
2020-12-02 17:15:32 +08:00
* @return array|bool
2020-11-21 19:53:01 +08:00
*/
2022-01-19 22:02:00 +08:00
public function create(int $user_id, string $fileName, int $fileSize)
2020-11-21 19:53:01 +08:00
{
$split_num = intval(ceil($fileSize / self::SPLIT_SIZE));
2021-04-20 16:30:57 +08:00
$data = [];
2022-01-19 22:02:00 +08:00
$data['type'] = 1;
$data['drive'] = FileDriveConstant::Local;
$data['upload_id'] = uniqid(strval(time()));
2021-04-20 16:30:57 +08:00
$data['user_id'] = $user_id;
2020-11-21 19:53:01 +08:00
$data['original_name'] = $fileName;
2021-04-20 16:30:57 +08:00
$data['file_ext'] = pathinfo($fileName, PATHINFO_EXTENSION);
$data['file_size'] = $fileSize;
2022-01-19 22:02:00 +08:00
$data['attr'] = new \stdClass();
$data['created_at'] = date("Y-m-d H:i:s");
$data['updated_at'] = date("Y-m-d H:i:s");
$data['path'] = sprintf("private/tmp/multipart/%s/%s.tmp", date("Ymd"), md5($data['upload_id']));
2020-11-21 19:53:01 +08:00
2021-04-22 16:14:34 +08:00
// 文件拆分数量
2021-04-20 16:30:57 +08:00
$data['split_num'] = $split_num;
2020-11-21 19:53:01 +08:00
$data['split_index'] = $split_num;
2022-01-19 22:02:00 +08:00
return SplitUpload::create($data) ? array_merge($data, ['split_size' => self::SPLIT_SIZE]) : false;
2020-11-21 19:53:01 +08:00
}
/**
2020-12-02 17:15:32 +08:00
* 保存拆分上传的文件
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
* @param UploadedFile $file 文件信息
2022-01-19 22:02:00 +08:00
* @param string $upload_id 上传临时问价hash名
2021-04-20 16:30:57 +08:00
* @param int $split_index 当前拆分文件索引
2020-12-02 17:15:32 +08:00
* @return bool
2020-11-21 19:53:01 +08:00
*/
2022-01-19 22:02:00 +08:00
public function upload(int $user_id, UploadedFile $file, string $upload_id, int $split_index)
2020-11-21 19:53:01 +08:00
{
2022-01-19 22:02:00 +08:00
$fileInfo = SplitUpload::select(['id', 'original_name', 'split_num', 'file_ext'])
->where([['user_id', '=', $user_id], ['upload_id', '=', $upload_id], ['type', '=', 1]])
2020-11-21 19:53:01 +08:00
->first();
2021-06-30 19:27:49 +08:00
if (!$fileInfo) return false;
2020-11-21 19:53:01 +08:00
2022-01-19 22:02:00 +08:00
$path = sprintf("private/tmp/%s/%s/%d-%s.tmp", date("Ymd"), md5($upload_id), $split_index, $upload_id);
2021-06-30 19:27:49 +08:00
try {
2022-01-19 22:02:00 +08:00
di()->get(Filesystem::class)->write($path, file_get_contents($file->getRealPath()));
2021-06-30 19:27:49 +08:00
} catch (\Exception $e) {
2020-11-21 19:53:01 +08:00
return false;
}
2022-01-19 22:02:00 +08:00
$info = SplitUpload::where('user_id', $user_id)->where('upload_id', $upload_id)->where('split_index', $split_index)->first();
2020-11-21 19:53:01 +08:00
if (!$info) {
2022-01-19 22:02:00 +08:00
return (bool)SplitUpload::create([
2021-04-20 16:30:57 +08:00
'user_id' => $user_id,
2022-01-19 22:02:00 +08:00
'type' => 2,
'drive' => FileDriveConstant::Local,
'upload_id' => $upload_id,
2020-11-21 19:53:01 +08:00
'original_name' => $fileInfo->original_name,
2021-04-20 16:30:57 +08:00
'split_index' => $split_index,
'split_num' => $fileInfo->split_num,
2022-01-19 22:02:00 +08:00
'path' => $path,
'attr' => new \stdClass(),
2021-04-20 16:30:57 +08:00
'file_ext' => $fileInfo->file_ext,
2022-01-19 22:02:00 +08:00
'file_size' => $file->getSize(),
'created_at' => date("Y-m-d H:i:s"),
'updated_at' => date("Y-m-d H:i:s"),
2021-04-20 16:30:57 +08:00
]);
2020-11-21 19:53:01 +08:00
}
return true;
}
/**
* 文件合并
*
2021-04-20 16:30:57 +08:00
* @param int $user_id 用户ID
2022-01-19 22:02:00 +08:00
* @param string $upload_id 上传临时问价hash名
2020-12-02 17:15:32 +08:00
* @return array|bool
2020-11-21 19:53:01 +08:00
*/
2022-01-19 22:02:00 +08:00
public function merge(int $user_id, string $upload_id)
2020-11-21 19:53:01 +08:00
{
2022-01-19 22:02:00 +08:00
$fileInfo = SplitUpload::select(['id', 'original_name', 'split_num', 'file_ext', 'file_size', 'path'])
2020-12-02 17:15:32 +08:00
->where('user_id', $user_id)
2022-01-19 22:02:00 +08:00
->where('upload_id', $upload_id)
->where('type', 1)
2020-12-02 17:15:32 +08:00
->first();
2021-06-30 19:27:49 +08:00
if (!$fileInfo) return false;
2020-11-21 19:53:01 +08:00
2022-01-19 22:02:00 +08:00
$files = SplitUpload::where('user_id', $user_id)
->where('upload_id', $upload_id)
->where('type', 2)
->orderBy('split_index')
->get(['split_index', 'path'])->toArray();
2020-12-02 17:15:32 +08:00
2021-06-30 19:27:49 +08:00
if (!$files || count($files) != $fileInfo->split_num) return false;
2020-11-21 19:53:01 +08:00
2021-07-23 21:34:29 +08:00
$filesystem = di()->get(Filesystem::class);
2021-06-30 19:27:49 +08:00
$root_path = $filesystem->getConfig()->get('root');
2022-01-19 22:02:00 +08:00
@mkdir(pathinfo("{$root_path}/{$fileInfo->path}", PATHINFO_DIRNAME));
2020-11-21 19:53:01 +08:00
foreach ($files as $file) {
2022-01-19 22:02:00 +08:00
file_put_contents("{$root_path}/{$fileInfo->path}", $filesystem->read($file['path']), FILE_APPEND);
2020-11-21 19:53:01 +08:00
}
return [
2022-01-19 22:02:00 +08:00
'path' => $fileInfo->path,
2020-11-21 19:53:01 +08:00
'tmp_file_name' => "{$fileInfo->original_name}.tmp",
'original_name' => $fileInfo->original_name,
2021-04-20 16:30:57 +08:00
'file_size' => $fileInfo->file_size
2020-11-21 19:53:01 +08:00
];
}
2021-08-15 22:48:57 +08:00
/**
* 清理超过24小时的临时文件
*/
public function clear()
{
// 24小时前
$time = time() - 60 * 60 * 24 * 1;
2022-01-19 22:02:00 +08:00
SplitUpload::where('file_type', 1)->where('upload_at', '<', $time)->select('upload_id')->chunk(100, function ($rows) {
2021-08-15 22:48:57 +08:00
foreach ($rows as $row) {
2022-01-19 22:02:00 +08:00
@di()->get(Filesystem::class)->deleteDir(pathinfo($row->path, PATHINFO_DIRNAME));
@SplitUpload::where('upload_id', $row->upload_id)->delete();
2021-08-15 22:48:57 +08:00
}
});
}
2020-11-21 19:53:01 +08:00
}