feat: 上传前判断大小、新文件插入第一位
This commit is contained in:
+2
-1
@@ -13,6 +13,7 @@ default_value = {
|
|||||||
'file_storage': 'local',
|
'file_storage': 'local',
|
||||||
'name': '文件快递柜-FileCodeBox',
|
'name': '文件快递柜-FileCodeBox',
|
||||||
'description': '开箱即用的文件快传系统',
|
'description': '开箱即用的文件快传系统',
|
||||||
|
'page_explain': '根据《中华人民共和国网络安全法》、《中华人民共和国刑法》、《中华人民共和国治安管理处罚法》等相关规定。 传播或存储违法、违规内容,会受到相关处罚,严重者将承担刑事责任。请勿上传非法文件,本站坚决配合相关部门,确保网络内容的安全,和谐,打造绿色网络环境。',
|
||||||
'keywords': 'FileCodeBox, 文件快递柜, 口令传送箱, 匿名口令分享文本, 文件',
|
'keywords': 'FileCodeBox, 文件快递柜, 口令传送箱, 匿名口令分享文本, 文件',
|
||||||
'max_save_seconds': 0,
|
'max_save_seconds': 0,
|
||||||
's3_access_key_id': '',
|
's3_access_key_id': '',
|
||||||
@@ -57,7 +58,7 @@ class Settings:
|
|||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
key, value = line.strip().split('=', maxsplit=1)
|
key, value = line.strip().split('=', maxsplit=1)
|
||||||
# 将字符串转换为原本的类型
|
# 将字符串转换为原本的类型
|
||||||
if not key.startswith('opendal_') and isinstance(default_value[key], int):
|
if key and not key.startswith('opendal_') and isinstance(default_value.get(key, ''), int):
|
||||||
value = int(value)
|
value = int(value)
|
||||||
default_value[key] = value
|
default_value[key] = value
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from "vue";
|
||||||
|
import { request } from "@/utils/request";
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
request({
|
||||||
|
url:'/',
|
||||||
|
method:'post'
|
||||||
|
}).then((res:any)=>{
|
||||||
|
if (res.code === 200) {
|
||||||
|
localStorage.setItem('config', JSON.stringify(res.detail));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import { request } from "@/utils/request";
|
|||||||
import { useFileDataStore } from "@/stores/fileData";
|
import { useFileDataStore } from "@/stores/fileData";
|
||||||
import { useFileBoxStore } from "@/stores/fileBox";
|
import { useFileBoxStore } from "@/stores/fileBox";
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useConfigStore } from "@/stores/config";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
|
const { config } = useConfigStore();
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const fileBoxStore = useFileBoxStore();
|
const fileBoxStore = useFileBoxStore();
|
||||||
const fileStore = useFileDataStore();
|
const fileStore = useFileDataStore();
|
||||||
@@ -38,6 +41,17 @@ const handleOnChangeFileList = (file: any) => {
|
|||||||
const handleHttpRequest = (options: any) => {
|
const handleHttpRequest = (options: any) => {
|
||||||
fileBoxStore.showFileBox = true;
|
fileBoxStore.showFileBox = true;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
if (options.file.size > config.uploadSize) {
|
||||||
|
fileStore.shareData.forEach((file: any) => {
|
||||||
|
if (file.uid === options.file.uid) {
|
||||||
|
ElMessage.error(t('msg.fileOverSize'));
|
||||||
|
file.status = 'fail';
|
||||||
|
file.code = t('msg.fileOverSize');
|
||||||
|
fileStore.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
formData.append('file', options.file);
|
formData.append('file', options.file);
|
||||||
formData.append('expire_value', props.shareData.expireValue);
|
formData.append('expire_value', props.shareData.expireValue);
|
||||||
formData.append('expire_style', props.shareData.expireStyle);
|
formData.append('expire_style', props.shareData.expireStyle);
|
||||||
@@ -63,6 +77,7 @@ const handleHttpRequest = (options: any) => {
|
|||||||
file.status = 'success';
|
file.status = 'success';
|
||||||
file.text = data.text;
|
file.text = data.text;
|
||||||
file.code = data.code;
|
file.code = data.code;
|
||||||
|
ElMessage.success(t('msg.fileUploadSuccess'));
|
||||||
fileStore.save();
|
fileStore.save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -70,7 +85,8 @@ const handleHttpRequest = (options: any) => {
|
|||||||
fileStore.shareData.forEach((file: any) => {
|
fileStore.shareData.forEach((file: any) => {
|
||||||
if (file.uid === options.file.uid) {
|
if (file.uid === options.file.uid) {
|
||||||
file.status = 'fail';
|
file.status = 'fail';
|
||||||
file.code = '上传失败';
|
file.code = t('msg.fileUploadFail');
|
||||||
|
ElMessage.error(t('msg.fileUploadFail'));
|
||||||
fileStore.save();
|
fileStore.save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export default {
|
|||||||
name: 'Website Name',
|
name: 'Website Name',
|
||||||
description: 'Website Description',
|
description: 'Website Description',
|
||||||
keywords: 'Keywords',
|
keywords: 'Keywords',
|
||||||
|
explain:'Use Explain',
|
||||||
uploadlimit:'Upload Limit',
|
uploadlimit:'Upload Limit',
|
||||||
errorlimit:'Error Limit',
|
errorlimit:'Error Limit',
|
||||||
background: 'Background Image',
|
background: 'Background Image',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createI18n } from 'vue-i18n' //引入vue-i18n组件
|
import { createI18n } from 'vue-i18n' //引入vue-i18n组件
|
||||||
import messages from './index'
|
import messages from './index'
|
||||||
const language = (
|
const language = (
|
||||||
navigator.language || 'zh'
|
navigator.language || 'zh_cn'
|
||||||
).toLowerCase();
|
).toLowerCase();
|
||||||
const lang = (localStorage.getItem('language') || language).replace(/-/, '_');
|
const lang = (localStorage.getItem('language') || language).replace(/-/, '_');
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import zh_cn from './zh_cn';
|
||||||
import zh from './zh';
|
import zh from './zh';
|
||||||
import en from './en';
|
import en from './en';
|
||||||
import zh_tw from './zh-tw'
|
import zh_tw from './zh_tw'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
zh,
|
zh_cn,
|
||||||
en,
|
en,
|
||||||
zh_tw
|
zh_tw,
|
||||||
|
zh
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@ export default {
|
|||||||
copySuccess: '复制成功',
|
copySuccess: '复制成功',
|
||||||
inputNotEmpty: '请输入五位取件码',
|
inputNotEmpty: '请输入五位取件码',
|
||||||
sendFileBox: '寄件箱',
|
sendFileBox: '寄件箱',
|
||||||
|
ok:'确定',
|
||||||
receiveFileBox: '收件箱',
|
receiveFileBox: '收件箱',
|
||||||
textDetail: '文本详情',
|
textDetail: '文本详情',
|
||||||
copy: '复 制',
|
copy: '复 制',
|
||||||
@@ -50,6 +51,7 @@ export default {
|
|||||||
name: '网站名称',
|
name: '网站名称',
|
||||||
description: '网站描述',
|
description: '网站描述',
|
||||||
uploadlimit: '上传限制',
|
uploadlimit: '上传限制',
|
||||||
|
explain:'界面说明',
|
||||||
errorlimit: '错误限制',
|
errorlimit: '错误限制',
|
||||||
keywords: '关键词',
|
keywords: '关键词',
|
||||||
background: '背景图片',
|
background: '背景图片',
|
||||||
@@ -109,5 +111,8 @@ export default {
|
|||||||
loginSuccess: '登录成功',
|
loginSuccess: '登录成功',
|
||||||
loginError: '登录失败',
|
loginError: '登录失败',
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
msg:{
|
||||||
|
fileOverSize: '文件过大',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
export default {
|
||||||
|
send: {
|
||||||
|
disclaimers:'免责声明',
|
||||||
|
prompt1: '将文字、文件拖、粘贴到此处,或 ',
|
||||||
|
prompt2: '天数<7或限制次数(24h后删除)',
|
||||||
|
prompt3: '请输入您要寄出的文本,支持MarkDown格式',
|
||||||
|
share: '分享',
|
||||||
|
textShare: '文本分享',
|
||||||
|
clickUpload: '点击上传',
|
||||||
|
pleaseInputExpireValue: '请输入有效期',
|
||||||
|
expireStyle: '过期方式',
|
||||||
|
expireData: {
|
||||||
|
day: '天数',
|
||||||
|
hour: '小时',
|
||||||
|
forever: '永久',
|
||||||
|
minute: '分钟',
|
||||||
|
count: '次数'
|
||||||
|
},
|
||||||
|
expireValue: {
|
||||||
|
day: '天',
|
||||||
|
hour: '时',
|
||||||
|
minute: '分',
|
||||||
|
count: '次'
|
||||||
|
},
|
||||||
|
fileType: {
|
||||||
|
file: '文件',
|
||||||
|
text: '文本'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fileBox: {
|
||||||
|
copySuccess: '复制成功',
|
||||||
|
inputNotEmpty: '请输入五位取件码',
|
||||||
|
sendFileBox: '寄件箱',
|
||||||
|
ok:'确定',
|
||||||
|
receiveFileBox: '收件箱',
|
||||||
|
textDetail: '文本详情',
|
||||||
|
copy: '复 制',
|
||||||
|
close: '关 闭',
|
||||||
|
delete: '删 除',
|
||||||
|
download: '点 击 下 载',
|
||||||
|
detail: '查 看 详 情',
|
||||||
|
copyLink: '复制链接',
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
about: {
|
||||||
|
source1: '本项目开源于Github:',
|
||||||
|
source2: 'FileCodeBox'
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
name: '网站名称',
|
||||||
|
description: '网站描述',
|
||||||
|
uploadlimit: '上传限制',
|
||||||
|
explain:'界面说明',
|
||||||
|
errorlimit: '错误限制',
|
||||||
|
keywords: '关键词',
|
||||||
|
background: '背景图片',
|
||||||
|
admin_token: '管理密码',
|
||||||
|
uploadSize: '文件大小',
|
||||||
|
uploadSizeNote: '最大文件大小,单位:(Bytes),1mb=1 * 1024 * 1024',
|
||||||
|
openUpload: {
|
||||||
|
title: '开启上传',
|
||||||
|
open: '开启游客上传',
|
||||||
|
close: '关闭游客上传',
|
||||||
|
note: '关闭之后需要登录后台方可上传',
|
||||||
|
},
|
||||||
|
file_storage: {
|
||||||
|
title: '存储引擎',
|
||||||
|
local: '本地存储',
|
||||||
|
s3: 'S3存储',
|
||||||
|
note: '更新后需要重启FileCodeBox',
|
||||||
|
},
|
||||||
|
mei: '每',
|
||||||
|
minute: '分钟',
|
||||||
|
upload: '上传',
|
||||||
|
files: '个文件',
|
||||||
|
allow: '允许',
|
||||||
|
errors: '次错误',
|
||||||
|
save: '保存',
|
||||||
|
saveSuccess: '保存成功',
|
||||||
|
},
|
||||||
|
fileView: {
|
||||||
|
code: '取件码',
|
||||||
|
prefix: '文件前缀',
|
||||||
|
suffix: '文件后缀',
|
||||||
|
text: '文本',
|
||||||
|
used_count: '已使用次数',
|
||||||
|
expired_count: '可用次数',
|
||||||
|
size: '文件大小',
|
||||||
|
expired_at: '过期时间',
|
||||||
|
file_path: '文件路径',
|
||||||
|
action: '操作',
|
||||||
|
delete: '删除',
|
||||||
|
delete_success: '删除成功',
|
||||||
|
forever: '永久有效',
|
||||||
|
unlimited_count: '不限次数',
|
||||||
|
download: '下载',
|
||||||
|
download_fail: '文件保存失败,请稍后再试~',
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
fileManage: '文件管理',
|
||||||
|
systemSetting: '系统设置',
|
||||||
|
about: '关于我们',
|
||||||
|
color: '颜色模式',
|
||||||
|
signout: '退出登录',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
managePassword: '管理密码',
|
||||||
|
passwordNotEmpty: '密码不能为空',
|
||||||
|
login: '登 录',
|
||||||
|
loginSuccess: '登录成功',
|
||||||
|
loginError: '登录失败',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
msg:{
|
||||||
|
fileOverSize: '文件过大',
|
||||||
|
fileUploadFail: '上传失败',
|
||||||
|
fileUploadSuccess: '上传成功',
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -50,6 +50,7 @@ export default {
|
|||||||
name: '網站名稱',
|
name: '網站名稱',
|
||||||
description: '網站描述',
|
description: '網站描述',
|
||||||
uploadlimit: '上傳限制',
|
uploadlimit: '上傳限制',
|
||||||
|
explain:'介面說明',
|
||||||
errorlimit: '錯誤限制',
|
errorlimit: '錯誤限制',
|
||||||
keywords: '關鍵詞',
|
keywords: '關鍵詞',
|
||||||
background: '背景圖片',
|
background: '背景圖片',
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
export const useConfigStore = defineStore('config', () => {
|
||||||
|
const config:any = ref(JSON.parse(localStorage.getItem('config') || '{}') || {}); // 配置
|
||||||
|
return { config };
|
||||||
|
});
|
||||||
@@ -9,12 +9,12 @@ export const useFileDataStore = defineStore('fileData', () => {
|
|||||||
localStorage.setItem('shareData', JSON.stringify(shareData));
|
localStorage.setItem('shareData', JSON.stringify(shareData));
|
||||||
}
|
}
|
||||||
function addReceiveData(data:any) {
|
function addReceiveData(data:any) {
|
||||||
receiveData.push(data);
|
receiveData.unshift(data);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addShareData(data:any) {
|
function addShareData(data:any) {
|
||||||
shareData.push(data);
|
shareData.unshift(data);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,19 +114,17 @@ async function saveFileByElementA(fileBlob: Blob, filename: string) {
|
|||||||
window.URL.revokeObjectURL(downloadUrl);
|
window.URL.revokeObjectURL(downloadUrl);
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveFileByWebApi(fileBlob: Blob, filename: string) {
|
async function saveFileByWebApi(fileBlob: Blob, filename: string) {
|
||||||
// 创建一个新句柄。
|
// 创建一个新句柄。
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const newHandle = await window.showSaveFilePicker({
|
const newHandle = await window.showSaveFilePicker({
|
||||||
suggestedName: filename,
|
suggestedName: filename,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 创建一个 FileSystemWritableFileStream 用于写入。
|
// 创建一个 FileSystemWritableFileStream 用于写入。
|
||||||
const writableStream = await newHandle.createWritable();
|
const writableStream = await newHandle.createWritable();
|
||||||
|
|
||||||
// 写入我们的文件。
|
// 写入我们的文件。
|
||||||
await writableStream.write(fileBlob);
|
await writableStream.write(fileBlob);
|
||||||
|
|
||||||
// 关闭文件并将内容写入磁盘。
|
// 关闭文件并将内容写入磁盘。
|
||||||
await writableStream.close();
|
await writableStream.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@
|
|||||||
<el-input v-model="config.keywords" />
|
<el-input v-model="config.keywords" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item size="large" :label="t('admin.settings.background')">
|
<el-form-item size="large" :label="t('admin.settings.background')">
|
||||||
<el-input v-model="config.background" />
|
<el-input v-model="config.background" placeholder="url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item size="large" :label="t('admin.settings.explain')">
|
||||||
|
<el-input type="textarea" v-model="config.page_explain" placeholder="explain" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item size="large" :label="t('admin.settings.admin_token')">
|
<el-form-item size="large" :label="t('admin.settings.admin_token')">
|
||||||
<el-input type="password" v-model="config.admin_token" />
|
<el-input type="password" v-model="config.admin_token" />
|
||||||
@@ -109,6 +112,7 @@ const config = ref({
|
|||||||
uploadMinute: 1,
|
uploadMinute: 1,
|
||||||
s3_access_key_id: '',
|
s3_access_key_id: '',
|
||||||
background: '',
|
background: '',
|
||||||
|
page_explain:'',
|
||||||
s3_secret_access_key: '',
|
s3_secret_access_key: '',
|
||||||
aws_session_token: '',
|
aws_session_token: '',
|
||||||
s3_signature_version: '',
|
s3_signature_version: '',
|
||||||
@@ -153,7 +157,7 @@ const submitSave = () => {
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
letter-spacing: 0.4rem;
|
letter-spacing: 0.4rem;
|
||||||
}
|
}
|
||||||
small{
|
small,.el-form-item__content{
|
||||||
color: #909399;
|
color: #909399;
|
||||||
margin-left: 0.4rem;
|
margin-left: 0.4rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ const input_status = reactive({
|
|||||||
'readonly': false,
|
'readonly': false,
|
||||||
'loading': false,
|
'loading': false,
|
||||||
})
|
})
|
||||||
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useConfigStore } from "@/stores/config";
|
||||||
|
|
||||||
|
const { config } = useConfigStore()
|
||||||
const noDialog = ()=>{
|
const noDialog = ()=>{
|
||||||
ElMessageBox.alert(t('send.alert'), t('send.disclaimers'), {
|
ElMessageBox.alert(config.explain, t('send.disclaimers'), {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: t('fileBox.ok'),
|
||||||
callback: () => {
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from tortoise.contrib.fastapi import register_tortoise
|
|||||||
|
|
||||||
from apps.base.views import share_api
|
from apps.base.views import share_api
|
||||||
from apps.admin.views import admin_api
|
from apps.admin.views import admin_api
|
||||||
|
from core.response import APIResponse
|
||||||
from core.settings import data_root, settings, BASE_DIR
|
from core.settings import data_root, settings, BASE_DIR
|
||||||
from core.tasks import delete_expire_files
|
from core.tasks import delete_expire_files
|
||||||
from core.utils import max_save_times_desc
|
from core.utils import max_save_times_desc
|
||||||
@@ -88,6 +89,14 @@ async def index():
|
|||||||
, media_type='text/html', headers={'Cache-Control': 'no-cache'})
|
, media_type='text/html', headers={'Cache-Control': 'no-cache'})
|
||||||
|
|
||||||
|
|
||||||
|
@app.post('/')
|
||||||
|
async def get_config():
|
||||||
|
return APIResponse(detail={
|
||||||
|
'explain': settings.page_explain,
|
||||||
|
'uploadSize': settings.uploadSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user