add:fronted
This commit is contained in:
+6
-4
@@ -9,16 +9,18 @@ from tortoise import fields
|
|||||||
from tortoise.models import Model
|
from tortoise.models import Model
|
||||||
from tortoise.contrib.pydantic import pydantic_model_creator
|
from tortoise.contrib.pydantic import pydantic_model_creator
|
||||||
|
|
||||||
|
from core.utils import get_now
|
||||||
|
|
||||||
|
|
||||||
class FileCodes(Model):
|
class FileCodes(Model):
|
||||||
id: Optional[int] = fields.IntField(pk=True)
|
id: Optional[int] = fields.IntField(pk=True)
|
||||||
code: Optional[int] = fields.CharField(description='分享码', max_length=255, index=True, unique=True)
|
code: Optional[int] = fields.CharField(description='分享码', max_length=255, index=True, unique=True)
|
||||||
prefix: Optional[str] = fields.CharField(max_length=255, description='前缀', default='')
|
prefix: Optional[str] = fields.CharField(max_length=255, description='前缀', default='')
|
||||||
suffix: Optional[str] = fields.CharField(max_length=255, description='后缀', default='')
|
suffix: Optional[str] = fields.CharField(max_length=255, description='后缀', default='')
|
||||||
uuid_file_name: Optional[str] = fields.CharField(max_length=255, description='uuid文件名')
|
uuid_file_name: Optional[str] = fields.CharField(max_length=255, description='uuid文件名', null=True)
|
||||||
file_path: Optional[str] = fields.CharField(max_length=255, description='文件路径')
|
file_path: Optional[str] = fields.CharField(max_length=255, description='文件路径', null=True)
|
||||||
size: Optional[int] = fields.IntField(description='文件大小', default=0)
|
size: Optional[int] = fields.IntField(description='文件大小', default=0)
|
||||||
|
text: Optional[str] = fields.TextField(description='文本内容', null=True)
|
||||||
expired_at: Optional[datetime] = fields.DatetimeField(null=True, description='过期时间')
|
expired_at: Optional[datetime] = fields.DatetimeField(null=True, description='过期时间')
|
||||||
expired_count: Optional[int] = fields.IntField(description='可用次数', default=0)
|
expired_count: Optional[int] = fields.IntField(description='可用次数', default=0)
|
||||||
used_count: Optional[int] = fields.IntField(description='已用次数', default=0)
|
used_count: Optional[int] = fields.IntField(description='已用次数', default=0)
|
||||||
@@ -27,7 +29,7 @@ class FileCodes(Model):
|
|||||||
|
|
||||||
async def is_expired(self):
|
async def is_expired(self):
|
||||||
if self.expired_at:
|
if self.expired_at:
|
||||||
return self.expired_at < datetime.now()
|
return self.expired_at < await get_now()
|
||||||
else:
|
else:
|
||||||
return self.expired_count != -1 and self.used_count >= self.expired_count
|
return self.expired_count != -1 and self.used_count >= self.expired_count
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ async def get_file_path_name(file: UploadFile):
|
|||||||
file_uuid = f"{uuid.uuid4().hex}"
|
file_uuid = f"{uuid.uuid4().hex}"
|
||||||
uuid_file_name = f"{file_uuid}{suffix}"
|
uuid_file_name = f"{file_uuid}{suffix}"
|
||||||
save_path = f"{path}/{uuid_file_name}"
|
save_path = f"{path}/{uuid_file_name}"
|
||||||
return path, suffix, prefix, uuid_file_name, file_uuid, save_path
|
return path, suffix, prefix, uuid_file_name, save_path
|
||||||
|
|
||||||
|
|
||||||
async def get_expire_info(expire_value: int, expire_style: str):
|
async def get_expire_info(expire_value: int, expire_style: str):
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# @Time : 2023/8/14 03:59
|
||||||
|
# @Author : Lan
|
||||||
|
# @File : views.py
|
||||||
|
# @Software: PyCharm
|
||||||
|
from fastapi import APIRouter, Form, UploadFile, File
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from apps.base.models import FileCodes
|
||||||
|
from apps.base.utils import get_expire_info, get_file_path_name
|
||||||
|
from core.storage import file_storage
|
||||||
|
|
||||||
|
share_api = APIRouter(
|
||||||
|
prefix='/share',
|
||||||
|
tags=['分享'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@share_api.post('/text/')
|
||||||
|
async def share_text(text: str = Form(...), expire_value: int = Form(default=1, gt=0), expire_style: str = Form(default='day')):
|
||||||
|
expired_at, expired_count, used_count, code = await get_expire_info(expire_value, expire_style)
|
||||||
|
await FileCodes.create(
|
||||||
|
code=code,
|
||||||
|
text=text,
|
||||||
|
expired_at=expired_at,
|
||||||
|
expired_count=expired_count,
|
||||||
|
used_count=used_count,
|
||||||
|
size=len(text),
|
||||||
|
prefix='文本分享'
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
'code': 200,
|
||||||
|
'msg': 'success',
|
||||||
|
'data': {
|
||||||
|
'code': code,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@share_api.post('/file/')
|
||||||
|
async def share_file(expire_value: int = Form(default=1, gt=0), expire_style: str = Form(default='day'), file: UploadFile = File(...)):
|
||||||
|
expired_at, expired_count, used_count, code = await get_expire_info(expire_value, expire_style)
|
||||||
|
path, suffix, prefix, uuid_file_name, save_path = await get_file_path_name(file)
|
||||||
|
await file_storage.save_file(file, save_path)
|
||||||
|
await FileCodes.create(
|
||||||
|
code=code,
|
||||||
|
prefix=prefix,
|
||||||
|
suffix=suffix,
|
||||||
|
uuid_file_name=uuid_file_name,
|
||||||
|
file_path=path,
|
||||||
|
size=file.size,
|
||||||
|
expired_at=expired_at,
|
||||||
|
expired_count=expired_count,
|
||||||
|
used_count=used_count,
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
'code': 200,
|
||||||
|
'msg': 'success',
|
||||||
|
'data': {
|
||||||
|
'code': code,
|
||||||
|
'name': file.filename,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SelectFileModel(BaseModel):
|
||||||
|
code: str
|
||||||
|
|
||||||
|
|
||||||
|
@share_api.post('/select/')
|
||||||
|
async def select_file(data: SelectFileModel):
|
||||||
|
file_code = await FileCodes.filter(code=data.code).first()
|
||||||
|
if not file_code:
|
||||||
|
return {
|
||||||
|
'code': 404,
|
||||||
|
'msg': '文件不存在',
|
||||||
|
}
|
||||||
|
if await file_code.is_expired():
|
||||||
|
return {
|
||||||
|
'code': 403,
|
||||||
|
'msg': '文件已过期',
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'code': 200,
|
||||||
|
'msg': 'success',
|
||||||
|
'data': {
|
||||||
|
'code': file_code.code,
|
||||||
|
'name': file_code.prefix + file_code.suffix,
|
||||||
|
'size': file_code.size,
|
||||||
|
'text': await file_storage.get_file_url(file_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -56,9 +56,11 @@ class S3FileStorage:
|
|||||||
await s3.delete_object(Bucket=self.bucket_name, Key=await file_code.get_file_path())
|
await s3.delete_object(Bucket=self.bucket_name, Key=await file_code.get_file_path())
|
||||||
|
|
||||||
async def get_file_url(self, file_code: FileCodes):
|
async def get_file_url(self, file_code: FileCodes):
|
||||||
|
if file_code.prefix == '文本分享':
|
||||||
|
return file_code.text
|
||||||
async with self.session.client("s3", endpoint_url=self.endpoint_url) as s3:
|
async with self.session.client("s3", endpoint_url=self.endpoint_url) as s3:
|
||||||
result = await s3.generate_presigned_url('get_object', Params={'Bucket': self.bucket_name, 'Key': await file_code.get_file_path()}, ExpiresIn=3600)
|
result = await s3.generate_presigned_url('get_object', Params={'Bucket': self.bucket_name, 'Key': await file_code.get_file_path()}, ExpiresIn=3600)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
file_storage = SystemFileStorage()
|
file_storage = S3FileStorage()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# @Author : Lan
|
# @Author : Lan
|
||||||
# @File : utils.py
|
# @File : utils.py
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
|
import datetime
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
@@ -23,3 +24,13 @@ async def get_random_string():
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
return ''.join(random.choice(r_s) for _ in range(5))
|
return ''.join(random.choice(r_s) for _ in range(5))
|
||||||
|
|
||||||
|
|
||||||
|
async def get_now():
|
||||||
|
"""
|
||||||
|
获取当前时间
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return datetime.datetime.now(
|
||||||
|
datetime.timezone(datetime.timedelta(hours=8))
|
||||||
|
)
|
||||||
|
|||||||
Vendored
+5
@@ -11,9 +11,11 @@ declare module 'vue' {
|
|||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
|
ElModal: typeof import('element-plus/es')['ElModal']
|
||||||
ElOption: typeof import('element-plus/es')['ElOption']
|
ElOption: typeof import('element-plus/es')['ElOption']
|
||||||
ElProgress: typeof import('element-plus/es')['ElProgress']
|
ElProgress: typeof import('element-plus/es')['ElProgress']
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
@@ -28,4 +30,7 @@ declare module 'vue' {
|
|||||||
UploadFile: typeof import('./src/components/UploadFile.vue')['default']
|
UploadFile: typeof import('./src/components/UploadFile.vue')['default']
|
||||||
UploadText: typeof import('./src/components/UploadText.vue')['default']
|
UploadText: typeof import('./src/components/UploadText.vue')['default']
|
||||||
}
|
}
|
||||||
|
export interface ComponentCustomProperties {
|
||||||
|
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,14 @@ const fileStore = useFileDataStore();
|
|||||||
const fileBoxStore = useFileBoxStore();
|
const fileBoxStore = useFileBoxStore();
|
||||||
import QrcodeVue from "qrcode.vue";
|
import QrcodeVue from "qrcode.vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
import { ref } from "vue";
|
||||||
|
const openUrl = (url: string) => {
|
||||||
|
if (url.startsWith('/')) {
|
||||||
|
url = window.location.origin + url;
|
||||||
|
}
|
||||||
|
window.open(url);
|
||||||
|
};
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const copyText = (text: any, style = 0) => {
|
const copyText = (text: any, style = 0) => {
|
||||||
if (style === 1) {
|
if (style === 1) {
|
||||||
@@ -20,22 +28,34 @@ const copyText = (text: any, style = 0) => {
|
|||||||
}
|
}
|
||||||
document.body.removeChild(temp);
|
document.body.removeChild(temp);
|
||||||
};
|
};
|
||||||
const route = useRoute();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-drawer append-to-body v-model="fileBoxStore.showFileBox" direction="btt" style="max-width: 1080px;margin: auto;"
|
<el-drawer :append-to-body="true" v-model="fileBoxStore.showFileBox" direction="btt" style="max-width: 1080px;margin: auto;"
|
||||||
size="400">
|
size="400">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h4>文件箱</h4>
|
<h4>文件箱</h4>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div v-if="route.name=='home'">
|
<div v-if="route.name=='home'" style="display: flex;flex-wrap: wrap;justify-content: center">
|
||||||
<el-card v-for="i in fileStore.receiveData" :key="i">
|
<el-card v-for="(value,index) in fileStore.receiveData" :key="index" style="margin: 0.5rem">
|
||||||
{{ i }}
|
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-button type="danger" @click="fileStore.deleteReceiveData(i)">删除</el-button>
|
<div style="display: flex;justify-content: space-between">
|
||||||
|
<h4 style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ value.name }}</h4>
|
||||||
|
<el-button size="small" type="danger" @click="fileStore.deleteReceiveData(index)">删除</el-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<div style="width: 200px;">
|
||||||
|
<div style="display: flex;justify-content: space-between">
|
||||||
|
<qrcode-vue :value="value.text" :size="100"></qrcode-vue>
|
||||||
|
<div style="display: flex;flex-direction: column;justify-content: space-around">
|
||||||
|
<el-tag size="large" style="cursor: pointer" @click="copyText(value.code)">{{ value.code }}</el-tag>
|
||||||
|
<el-tag v-if="value.name!=='文本分享'" size="large" type="success" style="cursor: pointer" @click="openUrl(value.text);">点击下载
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else size="large" type="success" style="cursor: pointer" @click="copyText(value.text);">点击复制</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="display: flex;flex-wrap: wrap;justify-content: center">
|
<div v-else style="display: flex;flex-wrap: wrap;justify-content: center">
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const props = defineProps({
|
|||||||
return {
|
return {
|
||||||
expireValue: 1,
|
expireValue: 1,
|
||||||
expireStyle: 'day',
|
expireStyle: 'day',
|
||||||
targetType: 'file',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +38,6 @@ const handleHttpRequest = (options: any) => {
|
|||||||
formData.append('file', options.file);
|
formData.append('file', options.file);
|
||||||
formData.append('expireValue', props.shareData.expireValue);
|
formData.append('expireValue', props.shareData.expireValue);
|
||||||
formData.append('expireStyle', props.shareData.expireStyle);
|
formData.append('expireStyle', props.shareData.expireStyle);
|
||||||
formData.append('targetType', props.shareData.targetType);
|
|
||||||
request(
|
request(
|
||||||
{
|
{
|
||||||
url: "share/file/",
|
url: "share/file/",
|
||||||
@@ -122,7 +120,6 @@ onMounted(()=>{
|
|||||||
<el-upload
|
<el-upload
|
||||||
class="upload-demo"
|
class="upload-demo"
|
||||||
drag
|
drag
|
||||||
action="http://127.0.0.1:8000/share"
|
|
||||||
multiple
|
multiple
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
ref="uploadBox"
|
ref="uploadBox"
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const props = defineProps({
|
|||||||
return {
|
return {
|
||||||
expireValue: 1,
|
expireValue: 1,
|
||||||
expireStyle: 'day',
|
expireStyle: 'day',
|
||||||
targetType: 'text',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,7 +22,6 @@ const handleSubmitShareText = ()=>{
|
|||||||
formData.append('text', shareText.value);
|
formData.append('text', shareText.value);
|
||||||
formData.append('expireValue', props.shareData.expireValue);
|
formData.append('expireValue', props.shareData.expireValue);
|
||||||
formData.append('expireStyle', props.shareData.expireStyle);
|
formData.append('expireStyle', props.shareData.expireStyle);
|
||||||
formData.append('targetType', props.shareData.targetType);
|
|
||||||
request({
|
request({
|
||||||
'url': 'share/text/',
|
'url': 'share/text/',
|
||||||
'method': 'post',
|
'method': 'post',
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const instance = axios.create({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const Request = axios.create({
|
const Request = axios.create({
|
||||||
baseURL: "http://localhost:8000",
|
baseURL: "http://localhost:12345",
|
||||||
timeout: 6000000,
|
timeout: 6000000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,65 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Upload, TakeawayBox } from '@element-plus/icons-vue';
|
import { Upload, TakeawayBox } from '@element-plus/icons-vue';
|
||||||
import { ref } from 'vue'
|
import { onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import CardTools from "@/components/CardTools.vue";
|
import CardTools from "@/components/CardTools.vue";
|
||||||
import { useFileBoxStore } from "@/stores/fileBox";
|
import { useFileBoxStore } from "@/stores/fileBox";
|
||||||
|
import { useFileDataStore } from "@/stores/fileData";
|
||||||
|
|
||||||
|
import { request } from "@/utils/request";
|
||||||
const fileBoxStore = useFileBoxStore();
|
const fileBoxStore = useFileBoxStore();
|
||||||
|
const fileStore = useFileDataStore();
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
const code = ref('')
|
const code = ref('')
|
||||||
|
const input_status = reactive({
|
||||||
|
'readonly': false,
|
||||||
|
'loading': false,
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
const query_code = route.query.code as string;
|
||||||
|
if (query_code) {
|
||||||
|
code.value = query_code
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(code, (newVal) => {
|
||||||
|
if (newVal.length === 5) {
|
||||||
|
input_status.readonly = true;
|
||||||
|
input_status.loading = true;
|
||||||
|
request({
|
||||||
|
'url': '/share/select',
|
||||||
|
'method': 'POST',
|
||||||
|
'data': {
|
||||||
|
'code': newVal
|
||||||
|
}
|
||||||
|
}).then((res: any) => {
|
||||||
|
input_status.readonly = false;
|
||||||
|
input_status.loading = false;
|
||||||
|
code.value = '';
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
fileBoxStore.showFileBox = true;
|
||||||
|
let flag = true;
|
||||||
|
fileStore.receiveData.forEach((file: any) => {
|
||||||
|
if (file.code === res.data.data.code) {
|
||||||
|
flag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (flag) {
|
||||||
|
fileStore.addReceiveData(res.data.data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(res.data.msg||'未知错误')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
const listenInput = (num: number) => {
|
const listenInput = (num: number) => {
|
||||||
console.log('listenInput',num)
|
if (code.value.length < 5) {
|
||||||
|
code.value += num
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -18,7 +68,7 @@ const listenInput = (num: number) => {
|
|||||||
<CardTools/>
|
<CardTools/>
|
||||||
<el-row style="text-align: center">
|
<el-row style="text-align: center">
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-input v-model="code" class="code-input" round autofocus clearable maxlength="5" placeholder="请输入五位取件码"/>
|
<el-input :readonly="input_status.readonly" v-loading="input_status.loading" v-model="code" class="code-input" round autofocus clearable maxlength="5" placeholder="请输入五位取件码"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span=8 v-for="i in 9" :key="i">
|
<el-col :span=8 v-for="i in 9" :key="i">
|
||||||
<el-button class="key-button" round @click="listenInput(i)">{{ i }}</el-button>
|
<el-button class="key-button" round @click="listenInput(i)">{{ i }}</el-button>
|
||||||
|
|||||||
Binary file not shown.
@@ -2,15 +2,10 @@
|
|||||||
# @Author : Lan
|
# @Author : Lan
|
||||||
# @File : main.py
|
# @File : main.py
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
import random
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from fastapi import FastAPI, UploadFile, File, Form
|
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
from tortoise.contrib.fastapi import register_tortoise
|
from tortoise.contrib.fastapi import register_tortoise
|
||||||
|
from apps.base.views import share_api
|
||||||
from apps.base.models import FileCodes
|
|
||||||
from apps.base.utils import get_file_path_name, get_expire_info
|
|
||||||
from core.storage import file_storage
|
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
@@ -42,43 +37,6 @@ register_tortoise(
|
|||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.include_router(
|
||||||
@app.post('/share/text/')
|
share_api
|
||||||
async def share_text(text: str = Form(...)):
|
)
|
||||||
return {
|
|
||||||
'code': 200,
|
|
||||||
'msg': 'success',
|
|
||||||
'data': {
|
|
||||||
'code': random.randint(100000, 999999),
|
|
||||||
'text': text,
|
|
||||||
'name': '文本分享',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@app.post('/share/file/')
|
|
||||||
async def share_file(expire_value: int = Form(default=1, gt=0), expire_style: str = Form(default='day'), file: UploadFile = File(...)):
|
|
||||||
expired_at, expired_count, used_count, code = await get_expire_info(expire_value, expire_style)
|
|
||||||
path, suffix, prefix, uuid_file_name, file_uuid, save_path = await get_file_path_name(file)
|
|
||||||
await file_storage.save_file(file, save_path)
|
|
||||||
file_code = await FileCodes.create(
|
|
||||||
code=code,
|
|
||||||
prefix=prefix,
|
|
||||||
suffix=suffix,
|
|
||||||
uuid_file_name=uuid_file_name,
|
|
||||||
file_path=path,
|
|
||||||
size=file.size,
|
|
||||||
expired_at=expired_at,
|
|
||||||
expired_count=expired_count,
|
|
||||||
used_count=used_count,
|
|
||||||
)
|
|
||||||
await file_storage.delete_file(file_code)
|
|
||||||
return {
|
|
||||||
'code': 200,
|
|
||||||
'msg': 'success',
|
|
||||||
'data': {
|
|
||||||
'code': code,
|
|
||||||
'text': '/share/{}'.format(random.randint(100000, 999999)),
|
|
||||||
'name': file.filename,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user