feat: 支持文件下载

This commit is contained in:
kuaifan 2022-01-24 14:28:48 +08:00
parent d516330a41
commit 870276fa48
4 changed files with 61 additions and 14 deletions

View File

@ -382,6 +382,9 @@ class FileController extends AbstractController
* @apiParam {Number|String} id * @apiParam {Number|String} id
* - Number 文件ID需要登录 * - Number 文件ID需要登录
* - String 链接码(不需要登录,用于预览) * - String 链接码(不需要登录,用于预览)
* @apiParam {String} down 直接下载
* - no: 浏览(默认)
* - yes: 下载
* *
* @apiSuccess {Number} ret 返回状态码1正确、0错误 * @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {String} msg 返回信息(错误描述)
@ -390,6 +393,7 @@ class FileController extends AbstractController
public function content() public function content()
{ {
$id = Request::input('id'); $id = Request::input('id');
$down = Request::input('down', 'no');
// //
if (Base::isNumber($id)) { if (Base::isNumber($id)) {
User::auth(); User::auth();
@ -405,7 +409,7 @@ class FileController extends AbstractController
} }
// //
$content = FileContent::whereFid($file->id)->orderByDesc('id')->first(); $content = FileContent::whereFid($file->id)->orderByDesc('id')->first();
return FileContent::formatContent($file->type, $content ? $content->content : []); return FileContent::formatContent($file, $content?->content, $down == 'yes');
} }
/** /**

View File

@ -41,22 +41,24 @@ class FileContent extends AbstractModel
use SoftDeletes; use SoftDeletes;
/** /**
* 获取格式内容 * 获取格式内容(或下载)
* @param $type * @param File $file
* @param $content * @param $content
* @param $download
* @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse * @return array|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/ */
public static function formatContent($type, $content) public static function formatContent($file, $content, $download = false)
{ {
$content = Base::json2array($content); $name = $file->ext ? "{$file->name}.{$file->ext}" : null;
if (in_array($type, ['word', 'excel', 'ppt'])) { $content = Base::json2array($content ?: []);
if (in_array($file->type, ['word', 'excel', 'ppt'])) {
if (empty($content)) { if (empty($content)) {
return Response::download(resource_path('assets/statics/office/empty.' . str_replace(['word', 'excel', 'ppt'], ['docx', 'xlsx', 'pptx'], $type))); return Response::download(resource_path('assets/statics/office/empty.' . str_replace(['word', 'excel', 'ppt'], ['docx', 'xlsx', 'pptx'], $file->type)), $name);
} }
return Response::download(public_path($content['url'])); return Response::download(public_path($content['url']), $name);
} }
if (empty($content)) { if (empty($content)) {
$content = match ($type) { $content = match ($file->type) {
'document' => [ 'document' => [
"type" => "md", "type" => "md",
"content" => "", "content" => "",
@ -69,15 +71,24 @@ class FileContent extends AbstractModel
], ],
default => json_decode('{}'), default => json_decode('{}'),
}; };
if ($download) {
abort(403, "This file is empty.");
}
} else { } else {
$content['preview'] = false; $content['preview'] = false;
if ($content['ext'] && !in_array($content['ext'], ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'])) { if ($file->ext && !in_array($file->ext, ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'])) {
$url = 'http://' . env('APP_IPPR') . '.3/' . $content['url']; if ($download) {
if (in_array($type, ['picture', 'image', 'tif', 'media'])) { return Response::download(public_path($content['url']), $name);
}
if (in_array($file->type, ['picture', 'image', 'tif', 'media'])) {
$url = Base::fillUrl($content['url']); $url = Base::fillUrl($content['url']);
} else {
$url = 'http://' . env('APP_IPPR') . '.3/' . $content['url'];
} }
$content['url'] = base64_encode($url); $content['url'] = base64_encode($url);
$content['preview'] = true; $content['preview'] = true;
} elseif ($download) {
abort(403, "This file not support download.");
} }
} }
return Base::retSuccess('success', [ 'content' => $content ]); return Base::retSuccess('success', [ 'content' => $content ]);

View File

@ -104,8 +104,14 @@
</template> </template>
<div class="file-menu" :style="contextMenuStyles"> <div class="file-menu" :style="contextMenuStyles">
<Dropdown trigger="custom" :visible="contextMenuVisible" transfer @on-clickoutside="handleClickContextMenuOutside" @on-visible-change="handleVisibleChangeMenu"> <Dropdown
<DropdownMenu slot="list" class="page-file-dropdown-menu"> trigger="custom"
:visible="contextMenuVisible"
transfer-class-name="page-file-dropdown-menu"
@on-clickoutside="handleClickContextMenuOutside"
@on-visible-change="handleVisibleChangeMenu"
transfer>
<DropdownMenu slot="list">
<template v-if="contextMenuItem.id"> <template v-if="contextMenuItem.id">
<DropdownItem @click.native="handleContextClick('open')">{{$L('打开')}}</DropdownItem> <DropdownItem @click.native="handleContextClick('open')">{{$L('打开')}}</DropdownItem>
<Dropdown placement="right-start" transfer> <Dropdown placement="right-start" transfer>
@ -133,6 +139,7 @@
<template v-else-if="contextMenuItem.share"> <template v-else-if="contextMenuItem.share">
<DropdownItem @click.native="handleContextClick('outshare')" divided>{{$L('退出共享')}}</DropdownItem> <DropdownItem @click.native="handleContextClick('outshare')" divided>{{$L('退出共享')}}</DropdownItem>
</template> </template>
<DropdownItem @click.native="handleContextClick('download')" :disabled="contextMenuItem.ext == ''">{{$L('下载')}}</DropdownItem>
<DropdownItem @click.native="handleContextClick('delete')" divided style="color:red">{{$L('删除')}}</DropdownItem> <DropdownItem @click.native="handleContextClick('delete')" divided style="color:red">{{$L('删除')}}</DropdownItem>
</template> </template>
<template v-else> <template v-else>
@ -902,6 +909,30 @@ export default {
this.linkGet() this.linkGet()
break; break;
case 'download':
if (!item.ext) {
$A.modalError("此文件不支持下载");
return;
}
$A.modalConfirm({
title: '下载文件',
content: `${item.name}.${item.ext} (${$A.bytesToSize(item.size)})`,
okText: '立即下载',
onOk: () => {
let url = $A.apiUrl(`file/content?id=${item.id}&down=yes&token=${this.userToken}`);
if (this.$Electron) {
try {
this.$Electron.shell.openExternal(url);
} catch (e) {
$A.modalError("下载失败");
}
} else {
window.open(url)
}
}
});
break;
case 'delete': case 'delete':
let typeName = item.type == 'folder' ? '文件夹' : '文件'; let typeName = item.type == 'folder' ? '文件夹' : '文件';
$A.modalConfirm({ $A.modalConfirm({

View File

@ -509,6 +509,7 @@
} }
.page-file-dropdown-menu { .page-file-dropdown-menu {
max-height: none !important;
.ivu-dropdown { .ivu-dropdown {
width: 100%; width: 100%;
.arrow-forward-item { .arrow-forward-item {