mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-05 04:44:13 +00:00
feat: 新增实现文件夹下载以及多文件压缩下载功能
This commit is contained in:
parent
e7239b3c5c
commit
930f55b080
@ -868,8 +868,7 @@ class DialogController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} api/dialog/msg/sendfiles 18. 群发文件上传
|
||||
* @api {post} api/dialog/msg/sendfiles 18. 群发文件上传
|
||||
* @api {post} api/dialog/msg/sendfiles 19. 群发文件上传
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
|
||||
@ -14,6 +14,7 @@ use App\Module\Ihttp;
|
||||
use Carbon\Carbon;
|
||||
use Redirect;
|
||||
use Request;
|
||||
use ZipArchive;
|
||||
|
||||
/**
|
||||
* @apiDefine file
|
||||
@ -969,4 +970,55 @@ class FileController extends AbstractController
|
||||
//
|
||||
return Base::retSuccess('success', $fileLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/file/download/zip 19. 压缩下载
|
||||
*
|
||||
* @apiDescription 需要token身份
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup file
|
||||
* @apiName download__zip
|
||||
*
|
||||
* @apiParam {Array} [ids] 文件ID,格式: [id, id2, id3]
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 返回数据
|
||||
*/
|
||||
public function download__zip()
|
||||
{
|
||||
$user = User::auth();
|
||||
$ids = Request::input('ids');
|
||||
if (!is_array($ids) || empty($ids)) {
|
||||
return Base::retError('Please select the downloaded file or folder');
|
||||
}
|
||||
|
||||
if (count($ids) > 100) {
|
||||
return Base::retError('You can only download up to 100 files or folders at a time');
|
||||
}
|
||||
|
||||
$files = [];
|
||||
AbstractModel::transaction(function() use ($user, $ids, &$files) {
|
||||
foreach ($ids as $id) {
|
||||
$files[] = File::getFilesTree(intval($id), $user, 0);
|
||||
}
|
||||
});
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
$zipName = 'temp/download/' . date("Ym") . '/' . $user->userid . '/file_' . date("YmdHis") . '.zip';
|
||||
$zipPath = storage_path('app/'.$zipName);
|
||||
Base::makeDir(dirname($zipPath));
|
||||
|
||||
if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
||||
return Base::retError('创建压缩文件失败');
|
||||
}
|
||||
|
||||
array_walk($files, function($file) use ($zip) {
|
||||
File::addFileTreeToZip($zip, $file);
|
||||
});
|
||||
|
||||
$zip->close();
|
||||
|
||||
return response()->download($zipPath, 'file_'. date("YmdHis") .'.zip')->deleteFileAfterSend(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,7 +317,7 @@ class File extends AbstractModel
|
||||
$data['full_name'] = $webkitRelativePath ?: $data['name'];
|
||||
//
|
||||
$addItem[] = $data;
|
||||
|
||||
|
||||
return ['data'=>$data,'addItem'=>$addItem];
|
||||
});
|
||||
}
|
||||
@ -832,4 +832,98 @@ class File extends AbstractModel
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件树
|
||||
*
|
||||
* @param int $fileId
|
||||
* @param User $user
|
||||
* @param int $permission
|
||||
* @param string $path
|
||||
* @return object
|
||||
*/
|
||||
public static function getFilesTree(int $fileId, User $user, $permission = 1, $path = '') {
|
||||
$file = File::permissionFind($fileId, $user, $permission);
|
||||
$file->path = ltrim($path . '/' . $file->name, '/');
|
||||
$file->children = [];
|
||||
if ($file->type == 'folder') {
|
||||
$files = $file->getFileList($user, $fileId, 'all', false);
|
||||
foreach ($files as &$childFile) {
|
||||
$childFile['path'] = $file->path . '/' . $childFile['name'];
|
||||
if ($childFile['type'] == 'folder') {
|
||||
$childFile['children'] = self::getFilesTree($childFile['id'], $user, $permission, $file->path);
|
||||
}
|
||||
}
|
||||
$file->children = $files;
|
||||
}
|
||||
$totalSize = self::calculateTotalSize($file);
|
||||
if ($totalSize > 1024 * 1024 * 1024) { // 1GB
|
||||
throw new ApiException('The total file size has exceeded 1GB, please download in batches');
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算文件夹文件总大小
|
||||
*
|
||||
* @param [type] $fileTree
|
||||
* @return float|int
|
||||
*/
|
||||
public static function calculateTotalSize($fileTree) {
|
||||
$totalSize = 0;
|
||||
if ($fileTree->type != 'folder') {
|
||||
$totalSize += $fileTree->size;
|
||||
} else {
|
||||
foreach ($fileTree->children as $childFile) {
|
||||
$totalSize += self::calculateTotalSize((object)$childFile);
|
||||
}
|
||||
}
|
||||
return $totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件夹文件添加到压缩文件
|
||||
*
|
||||
* @param [type] $zip
|
||||
* @param object $file
|
||||
* @return void
|
||||
*/
|
||||
public static function addFileTreeToZip($zip, $file)
|
||||
{
|
||||
if ($file->type != 'folder') {
|
||||
$content = FileContent::whereFid($file->id)->orderByDesc('id')->first();
|
||||
$content = Base::json2array($content?->content ?: []);
|
||||
$typeExtensions = [
|
||||
'word' => 'docx',
|
||||
'excel' => 'xlsx',
|
||||
'ppt' => 'pptx',
|
||||
];
|
||||
if (array_key_exists($file->type, $typeExtensions)) {
|
||||
$filePath = empty($content) ? public_path('assets/office/empty.' . $typeExtensions[$file->type]) : public_path($content['url']);
|
||||
}
|
||||
|
||||
$relativePath = $file->path . '.' . $file->ext;
|
||||
if (file_exists($filePath)) {
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
} else {
|
||||
if (empty($content['url'])) {
|
||||
$zip->addFromString($relativePath, $content['content']);
|
||||
} else {
|
||||
$filePath = public_path($content['url']);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isset($file->children)) {
|
||||
foreach ($file->children as $childFile) {
|
||||
try {
|
||||
self::addFileTreeToZip($zip, (object)$childFile);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 在压缩包中创建文件夹
|
||||
$zip->addEmptyDir($file->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +49,10 @@
|
||||
<Icon type="ios-cut" />
|
||||
{{$L('剪切')}}
|
||||
</Button>
|
||||
<Button size="small" type="info" @click="downloadZipFile(selectIds)">
|
||||
<Icon type="ios-download-outline" />
|
||||
{{$L('压缩下载')}}
|
||||
</Button>
|
||||
<Button size="small" type="error" @click="deleteFile(selectIds)">
|
||||
<Icon type="ios-trash" />
|
||||
{{$L('删除')}}
|
||||
@ -195,6 +199,7 @@
|
||||
<DropdownItem name="send" :disabled="contextMenuItem.type == 'folder'">{{$L('发送')}}</DropdownItem>
|
||||
<DropdownItem name="link" :divided="contextMenuItem.userid != userId && !contextMenuItem.share" :disabled="contextMenuItem.type == 'folder'">{{$L('链接')}}</DropdownItem>
|
||||
<DropdownItem name="download" :disabled="contextMenuItem.ext == ''">{{$L('下载')}}</DropdownItem>
|
||||
<DropdownItem name="downloadzip">{{$L('压缩下载')}}</DropdownItem>
|
||||
|
||||
<DropdownItem name="delete" divided style="color:red">{{$L('删除')}}</DropdownItem>
|
||||
</template>
|
||||
@ -1260,6 +1265,10 @@ export default {
|
||||
});
|
||||
break;
|
||||
|
||||
case 'downloadzip':
|
||||
this.downloadZipFile([item.id])
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
this.deleteFile([item.id])
|
||||
break;
|
||||
@ -1396,6 +1405,26 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
downloadZipFile(ids){
|
||||
if (ids.length === 0) {
|
||||
return
|
||||
}
|
||||
const firstFile = this.fileLists.find(({ id }) => id === ids[0]) || {};
|
||||
const allFolder = !ids.some(id => this.fileLists.some(({ type, id: itemId }) => type !== 'folder' && itemId === id));
|
||||
const typeName = allFolder ? "文件夹" : "文件";
|
||||
const fileName = ids.length === 1 ? `【${firstFile.name}】${typeName}` : `【${firstFile.name}】等${ids.length}个${typeName}`;
|
||||
|
||||
$A.modalConfirm({
|
||||
title: '下载文件',
|
||||
content: `你确定要下载${fileName}吗?`,
|
||||
okText: '立即下载',
|
||||
onOk: () => {
|
||||
const idsParam = ids.join('&ids[]=');
|
||||
this.$store.dispatch('downUrl', $A.apiUrl(`file/download/zip?ids[]=${idsParam}`));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
autoBlur(id) {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs['input_' + id]) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user