perf: 上传文件夹应该保持目录结构

This commit is contained in:
kuaifan 2022-01-25 14:46:52 +08:00
parent d0a432164d
commit c7700bdfef
4 changed files with 47 additions and 13 deletions

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Exceptions\ApiException;
use App\Models\AbstractModel; use App\Models\AbstractModel;
use App\Models\File; use App\Models\File;
use App\Models\FileContent; use App\Models\FileContent;
@ -546,6 +547,7 @@ class FileController extends AbstractController
$user = User::auth(); $user = User::auth();
// //
$pid = intval(Request::input('pid')); $pid = intval(Request::input('pid'));
$webkitRelativePath = Request::input('webkitRelativePath');
// //
$userid = $user->userid; $userid = $user->userid;
if ($pid > 0) { if ($pid > 0) {
@ -560,6 +562,33 @@ class FileController extends AbstractController
} }
} }
// //
$dirs = explode("/", $webkitRelativePath);
AbstractModel::transaction(function() use ($user, $userid, $dirs, &$pid) {
while (count($dirs) > 1) {
$dirName = array_shift($dirs);
if ($dirName) {
$dirRow = File::wherePid($pid)->whereType('folder')->whereName($dirName)->lockForUpdate()->first();
if (empty($dirRow)) {
$dirRow = File::createInstance([
'pid' => $pid,
'type' => 'folder',
'name' => $dirName,
'userid' => $userid,
'created_id' => $user->userid,
]);
if ($dirRow->save()) {
$tmpRow = File::find($dirRow->id);
$tmpRow->pushMsg('add', $tmpRow);
}
}
if (empty($dirRow)) {
throw new ApiException('创建文件夹失败');
}
$pid = $dirRow->id;
}
}
});
//
$path = 'uploads/file/' . date("Ym") . '/u' . $user->userid . '/'; $path = 'uploads/file/' . date("Ym") . '/u' . $user->userid . '/';
$data = Base::upload([ $data = Base::upload([
"file" => Request::file('files'), "file" => Request::file('files'),
@ -585,7 +614,7 @@ class FileController extends AbstractController
'pdf' => "pdf", 'pdf' => "pdf",
'txt' => "txt", 'txt' => "txt",
'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css',
'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', 'makefile', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile',
'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php',
'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile',
'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml',
@ -604,7 +633,8 @@ class FileController extends AbstractController
'created_id' => $user->userid, 'created_id' => $user->userid,
]); ]);
// 开始创建 // 开始创建
return AbstractModel::transaction(function () use ($type, $user, $data, $file) { return AbstractModel::transaction(function () use ($webkitRelativePath, $type, $user, $data, $file) {
$file->size = $data['size'] * 1024;
$file->save(); $file->save();
// //
$content = FileContent::createInstance([ $content = FileContent::createInstance([
@ -616,16 +646,16 @@ class FileController extends AbstractController
'url' => $data['path'] 'url' => $data['path']
], ],
'text' => '', 'text' => '',
'size' => $data['size'] * 1024, 'size' => $file->size,
'userid' => $user->userid, 'userid' => $user->userid,
]); ]);
$content->save(); $content->save();
// //
$file->size = $content->size; $tmpRow = File::find($file->id);
$file->save(); $tmpRow->pushMsg('add', $tmpRow);
// //
$data = File::find($file->id); $data = $tmpRow->toArray();
$data->pushMsg('add', $data); $data['full_name'] = $webkitRelativePath ?: $data['name'];
return Base::retSuccess($data['name'] . ' 上传成功', $data); return Base::retSuccess($data['name'] . ' 上传成功', $data);
}); });
} }

View File

@ -2255,7 +2255,7 @@ class Base
'pdf', 'pdf',
'txt', 'txt',
'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css',
'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', 'makefile', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile',
'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php',
'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile',
'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml',

View File

@ -64,7 +64,7 @@
"stylus-loader": "^6.2.0", "stylus-loader": "^6.2.0",
"tinymce": "^5.10.2", "tinymce": "^5.10.2",
"tui-calendar-hi": "^1.15.1-5", "tui-calendar-hi": "^1.15.1-5",
"view-design-hi": "^4.7.0-7", "view-design-hi": "^4.7.0-8",
"vue": "^2.6.14", "vue": "^2.6.14",
"vue-clipboard2": "^0.3.3", "vue-clipboard2": "^0.3.3",
"vue-emoji-picker": "^1.0.3", "vue-emoji-picker": "^1.0.3",

View File

@ -160,12 +160,12 @@
<div v-if="uploadShow && uploadList.length > 0" class="file-upload-list"> <div v-if="uploadShow && uploadList.length > 0" class="file-upload-list">
<div class="upload-wrap"> <div class="upload-wrap">
<div class="title"> <div class="title">
{{$L('上传列表')}} {{$L('上传列表')}} ({{uploadList.length}})
<em v-if="uploadList.find(({status}) => status === 'finished')" @click="uploadClear">{{$L('清空已完成')}}</em> <em v-if="uploadList.find(({status}) => status === 'finished')" @click="uploadClear">{{$L('清空已完成')}}</em>
</div> </div>
<ul class="content"> <ul class="content">
<li v-for="(item, index) in uploadList"> <li v-for="(item, index) in uploadList" :key="index" v-if="index < 100">
<AutoTip class="file-name">{{item.name}}</AutoTip> <AutoTip class="file-name">{{uploadName(item)}}</AutoTip>
<AutoTip v-if="item.status === 'finished' && item.response && item.response.ret !== 1" class="file-error">{{item.response.msg}}</AutoTip> <AutoTip v-if="item.status === 'finished' && item.response && item.response.ret !== 1" class="file-error">{{item.response.msg}}</AutoTip>
<Progress v-else :percent="uploadPercentageParse(item.percentage)" :stroke-width="5" /> <Progress v-else :percent="uploadPercentageParse(item.percentage)" :stroke-width="5" />
<Icon class="file-close" type="ios-close-circle-outline" @click="uploadList.splice(index, 1)"/> <Icon class="file-close" type="ios-close-circle-outline" @click="uploadList.splice(index, 1)"/>
@ -409,7 +409,7 @@ export default {
'pdf', 'pdf',
'txt', 'txt',
'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css', 'htaccess', 'htgroups', 'htpasswd', 'conf', 'bat', 'cmd', 'cpp', 'c', 'cc', 'cxx', 'h', 'hh', 'hpp', 'ino', 'cs', 'css',
'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile', 'makefile', 'dockerfile', 'go', 'html', 'htm', 'xhtml', 'vue', 'we', 'wpy', 'java', 'js', 'jsm', 'jsx', 'json', 'jsp', 'less', 'lua', 'makefile', 'gnumakefile',
'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php', 'ocamlmakefile', 'make', 'md', 'markdown', 'mysql', 'nginx', 'ini', 'cfg', 'prefs', 'm', 'mm', 'pl', 'pm', 'p6', 'pl6', 'pm6', 'pgsql', 'php',
'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile', 'inc', 'phtml', 'shtml', 'php3', 'php4', 'php5', 'phps', 'phpt', 'aw', 'ctp', 'module', 'ps1', 'py', 'r', 'rb', 'ru', 'gemspec', 'rake', 'guardfile', 'rakefile',
'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml', 'gemfile', 'rs', 'sass', 'scss', 'sh', 'bash', 'bashrc', 'sql', 'sqlserver', 'swift', 'ts', 'typescript', 'str', 'vbs', 'vb', 'v', 'vh', 'sv', 'svh', 'xml',
@ -1163,6 +1163,10 @@ export default {
}) })
}, },
uploadName(item) {
return $A.getObject(item, 'response.data.full_name') || item.name
},
/********************文件上传部分************************/ /********************文件上传部分************************/
uploadUpdate(fileList) { uploadUpdate(fileList) {