Init
This commit is contained in:
+156
@@ -0,0 +1,156 @@
|
||||
media/
|
||||
logs/
|
||||
.idea
|
||||
static/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
*.env
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test.pdf / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# Project
|
||||
.vscode
|
||||
.DS_Store
|
||||
for_test.py
|
||||
.html
|
||||
/evaluate/temp.py
|
||||
/evaluation/back.json
|
||||
.env*
|
||||
.backup/
|
||||
/cloc-1.64.exe
|
||||
*.db
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
FROM python:3.9.5
|
||||
LABEL author="Lan"
|
||||
LABEL email="vast@tom.com"
|
||||
LABEL version="1.0"
|
||||
|
||||
|
||||
COPY . /app
|
||||
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
RUN echo 'Asia/Shanghai' >/etc/timezone
|
||||
WORKDIR /app
|
||||
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||
EXPOSE 123456
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "12345"]
|
||||
BIN
Binary file not shown.
+23
@@ -0,0 +1,23 @@
|
||||
import datetime
|
||||
|
||||
from sqlalchemy import create_engine, DateTime
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import Boolean, Column, Integer, String
|
||||
|
||||
engine = create_engine('sqlite:///database.db', connect_args={"check_same_thread": False})
|
||||
Base = declarative_base()
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
|
||||
class Codes(Base):
|
||||
__tablename__ = 'codes'
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
code = Column(String(10), unique=True, index=True)
|
||||
key = Column(String(30), unique=True, index=True)
|
||||
name = Column(String(500))
|
||||
size = Column(Integer)
|
||||
type = Column(String(20))
|
||||
text = Column(String(500))
|
||||
used = Column(Boolean, default=False)
|
||||
use_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
|
||||
@@ -0,0 +1,124 @@
|
||||
import datetime
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from fastapi import FastAPI, Depends, UploadFile, Form, File
|
||||
from sqlalchemy.orm import Session
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse
|
||||
import random
|
||||
|
||||
from starlette.staticfiles import StaticFiles
|
||||
|
||||
import database
|
||||
from database import engine, SessionLocal, Base
|
||||
|
||||
Base.metadata.create_all(bind=engine)
|
||||
app = FastAPI()
|
||||
if not os.path.exists('./static'):
|
||||
os.makedirs('./static')
|
||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||
# 过期时间
|
||||
exp_hour = 24
|
||||
# 允许错误次数
|
||||
error_count = 5
|
||||
# 禁止分钟数
|
||||
error_minute = 60
|
||||
|
||||
error_ip_count = {}
|
||||
|
||||
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def get_code(db: Session = Depends(get_db)):
|
||||
code = random.randint(10000, 99999)
|
||||
while db.query(database.Codes).filter(database.Codes.code == code).first():
|
||||
code = random.randint(10000, 99999)
|
||||
return str(code)
|
||||
|
||||
|
||||
def get_file_name(key, ext, file):
|
||||
now = datetime.datetime.now()
|
||||
path = f'./static/upload/{now.year}/{now.month}/{now.day}/'
|
||||
name = f'{key}.{ext}'
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
file = file.file.read()
|
||||
with open(f'{os.path.join(path, name)}', 'wb') as f:
|
||||
f.write(file)
|
||||
return key, len(file), path[1:] + name
|
||||
|
||||
|
||||
@app.get('/')
|
||||
async def index():
|
||||
with open('templates/index.html', 'r') as f:
|
||||
return HTMLResponse(f.read())
|
||||
|
||||
|
||||
@app.post('/')
|
||||
async def index(request: Request, code: str, db: Session = Depends(get_db)):
|
||||
info = db.query(database.Codes).filter(database.Codes.code == code).first()
|
||||
error = error_ip_count.get(request.client.host, {'count': 0, 'time': datetime.datetime.now()})
|
||||
if error['count'] > error_count:
|
||||
if datetime.datetime.now() - error['time'] < datetime.timedelta(minutes=error_minute):
|
||||
return {'code': 404, 'msg': '请求过于频繁,请稍后再试'}
|
||||
else:
|
||||
error['count'] = 0
|
||||
else:
|
||||
if not info:
|
||||
error['count'] += 1
|
||||
error_ip_count[request.client.host] = error
|
||||
return {'code': 404, 'msg': f'取件码错误,错误5次将被禁止10分钟'}
|
||||
else:
|
||||
return {'code': 200, 'msg': '取件成功,请点击库查看', 'data': info}
|
||||
|
||||
|
||||
@app.get('/share')
|
||||
async def share():
|
||||
with open('templates/upload.html', 'r') as f:
|
||||
return HTMLResponse(f.read())
|
||||
|
||||
|
||||
@app.post('/share')
|
||||
async def share(text: str = Form(default=None), file: UploadFile = File(default=None), db: Session = Depends(get_db)):
|
||||
cutoff_time = datetime.datetime.now() - datetime.timedelta(hours=exp_hour)
|
||||
db.query(database.Codes).filter(database.Codes.use_time < cutoff_time).delete()
|
||||
db.commit()
|
||||
code = get_code(db)
|
||||
if text:
|
||||
info = database.Codes(
|
||||
code=code,
|
||||
text=text,
|
||||
type='text/plain',
|
||||
key=uuid.uuid4().hex,
|
||||
size=len(text),
|
||||
used=True,
|
||||
name='分享文本'
|
||||
)
|
||||
db.add(info)
|
||||
db.commit()
|
||||
return {'code': 200, 'msg': '上传成功,请点击文件库查看',
|
||||
'data': {'code': code, 'name': '分享文本', 'text': text}}
|
||||
elif file:
|
||||
key, size, full_path = get_file_name(uuid.uuid4().hex, file.filename.split('.')[-1], file)
|
||||
info = database.Codes(
|
||||
code=code,
|
||||
text=full_path,
|
||||
type=file.content_type,
|
||||
key=key,
|
||||
size=size,
|
||||
used=True,
|
||||
name=file.filename
|
||||
)
|
||||
db.add(info)
|
||||
db.commit()
|
||||
return {'code': 200, 'msg': '上传成功,请点击文件库查看',
|
||||
'data': {'code': code, 'name': file.filename, 'text': full_path}}
|
||||
else:
|
||||
return {'code': 422, 'msg': '参数错误', 'data': []}
|
||||
@@ -0,0 +1,34 @@
|
||||
# 口令传送箱
|
||||
|
||||
## 主要特色
|
||||
|
||||
- [x] 拖拽,复制粘贴上传
|
||||
- [x] 文件口令传输
|
||||
- [x] 分享文件:多种上传方式供你选择
|
||||
- [x] 分享文本:直接复制粘贴直接上传
|
||||
- [x] 防爆破:错误五次拉黑十分钟
|
||||
- [x] 完全匿名:不记录任何信息
|
||||
- [x] 无需注册:无需注册,无需登录
|
||||
- [x] Sqlite3数据库:无需安装数据库
|
||||
|
||||
## 部署方式
|
||||
|
||||
### 服务端部署
|
||||
|
||||
1. 安装Python3
|
||||
2. 拉取代码,解压缩
|
||||
3. 安装依赖包:`pip install -r requirements.txt`
|
||||
4. 运行` uvicorn main:app --host 0.0.0.0 --port 12345`
|
||||
5. 然后你自己看怎么进程守护吧
|
||||
|
||||
### 宝塔部署
|
||||
|
||||
1. 安装宝塔Python Manager
|
||||
2. 然后你自己看着填吧
|
||||
|
||||
### Docker部署
|
||||
|
||||
```bash
|
||||
docker build --file Dockerfile --tag filecodebox .
|
||||
docker run -d -p 12345:12345 --name filecodebox filecodebox
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
anyio==3.6.2
|
||||
click==8.1.3
|
||||
fastapi==0.88.0
|
||||
h11==0.14.0
|
||||
httptools==0.5.0
|
||||
idna==3.4
|
||||
pydantic==1.10.2
|
||||
python-dotenv==0.21.0
|
||||
python-multipart==0.0.5
|
||||
PyYAML==6.0
|
||||
six==1.16.0
|
||||
sniffio==1.3.0
|
||||
SQLAlchemy==1.4.44
|
||||
starlette==0.22.0
|
||||
typing_extensions==4.4.0
|
||||
uvicorn==0.20.0
|
||||
uvloop==0.17.0
|
||||
watchfiles==0.18.1
|
||||
websockets==10.4
|
||||
@@ -0,0 +1,257 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
||||
<!-- 引入组件库 -->
|
||||
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||||
<title>取件箱-口令传送箱</title>
|
||||
<style>
|
||||
.qu .el-button {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 0.2rem;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qu .el-input__inner {
|
||||
height: 100px;
|
||||
margin: 1rem 0;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="text-align: center;">
|
||||
<el-row v-if="tool==0" class="qu" style="width:400px;margin: auto">
|
||||
<el-card style="padding-bottom: 1rem">
|
||||
<el-col :span="24">
|
||||
<el-input autofocus @input="inputing" clearable v-model:value="code" maxlength="5"
|
||||
:disabled="inout_disable"
|
||||
placeholder="请输入取件码"></el-input>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('1')">1</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('2')">2</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('3')">3</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('4')">4</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('5')">5</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('6')">6</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('7')">7</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('8')">8</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('9')">9</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="tool=1">寄</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="inputNumber('0')">0</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="quDrawer=true">取</el-button>
|
||||
</el-col>
|
||||
</el-card>
|
||||
</el-row>
|
||||
<el-row v-else style="width:400px;margin: auto">
|
||||
<el-col :span="24" style="margin: 1rem 0">
|
||||
<el-card>
|
||||
<el-upload
|
||||
drag
|
||||
action="/share"
|
||||
multiple
|
||||
:on-success="successUpload"
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖、粘贴到此处,或<em>点击上传</em>,24h后删除</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<el-button @click="tool=0">去取件</el-button>
|
||||
<el-button @click="cunDrawer=true">文件箱</el-button>
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div style="text-align: center; margin-top: 1rem;color: #606266">
|
||||
<span> By: <a style="text-decoration: none;color: #606266" target="_blank"
|
||||
href="https://github.com/vastsa/FileShare">Lan</a></span>
|
||||
</div>
|
||||
<el-drawer
|
||||
title="文件库"
|
||||
:visible.sync="quDrawer"
|
||||
:direction="direction"
|
||||
size="50%"
|
||||
>
|
||||
<el-card v-for="(file,index) in files" :key="index" class="box-card">
|
||||
<div style="cursor: pointer;text-align: left">
|
||||
<div>取件码:${ file.code }</div>
|
||||
<div>文件名:${ file.name }</div>
|
||||
<div v-if="file.name==='分享文本'">
|
||||
<span>内 容:${ file.text }</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>链 接:</span>
|
||||
<a :href="file.text" target="_blank"
|
||||
style="color: #1E9FFF;text-underline: none"
|
||||
type="primary">点击下载</a>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-empty v-if="files.length===0" description="请输入取件码,收取文件"></el-empty>
|
||||
</el-drawer>
|
||||
<el-drawer
|
||||
title="文件库"
|
||||
:visible.sync="cunDrawer"
|
||||
direction="btt"
|
||||
size="50%">
|
||||
<el-card>
|
||||
<el-empty v-if="files.length===0" description="请上传文件"></el-empty>
|
||||
<el-card style="margin-top: 0.2rem" v-for="file in files" :key="file.code">
|
||||
<el-row>
|
||||
<el-col :span="24" style="line-height: 45px">
|
||||
${ file.name }
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
取件码:<h1 style="margin: 0;display: inline">${ file.code }</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<!-- import Vue before Element -->
|
||||
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
|
||||
<!-- import JavaScript -->
|
||||
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||||
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
delimiters: ['${', '}'],
|
||||
data: function () {
|
||||
return {
|
||||
code: '',
|
||||
inout_disable: false,
|
||||
files: [],
|
||||
quDrawer: false,
|
||||
cunDrawer: false,
|
||||
direction: 'btt',
|
||||
tool: 0
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.code = window.location.search.substring('code=='.length)
|
||||
if (this.code) {
|
||||
this.get_file();
|
||||
}
|
||||
|
||||
const that = this
|
||||
document.addEventListener('paste', function (event) {
|
||||
if (that.tool === 1) {
|
||||
const items = event.clipboardData && event.clipboardData.items;
|
||||
if (items && items.length) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].kind === 'string') {
|
||||
if (items[i].type.match(/^text\/plain/)) {
|
||||
const FileData = new FormData();
|
||||
that.$message('剪切板文字正在上传,请稍等');
|
||||
items[i].getAsString(function (str) {
|
||||
FileData.append('text', str);
|
||||
axios.post('/share', FileData)
|
||||
.then(function (response) {
|
||||
that.$message({'message': response.data.msg, 'type': 'success'});
|
||||
that.files.push(response.data.data)
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message({'message': error.data.msg, 'type': 'error'});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const file = items[i].getAsFile();
|
||||
that.$message('剪切板文件正在上传,请稍等');
|
||||
const FileData = new FormData();
|
||||
FileData.append('file', file || '');
|
||||
axios.post('/share', FileData).then(async res => {
|
||||
that.files.push(res.data.data);
|
||||
that.$message({'message': res.data.msg, 'type': 'success'});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
inputing: function (value) {
|
||||
if (value.length === 5) {
|
||||
this.inout_disable = true;
|
||||
this.get_file();
|
||||
}
|
||||
},
|
||||
get_file: function () {
|
||||
const that = this;
|
||||
axios.post('?code=' + this.code).then(function (response) {
|
||||
if (response.data.code === 404) {
|
||||
that.$message({
|
||||
message: response.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
} else {
|
||||
that.files.push(response.data.data);
|
||||
that.$message({
|
||||
message: response.data.msg,
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
that.code = '';
|
||||
that.inout_disable = false
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
inputNumber: function (number) {
|
||||
if (number === 'C') {
|
||||
this.code = '';
|
||||
} else if (number === 'X') {
|
||||
this.code = this.code.substring(0, this.code.length - 1);
|
||||
} else {
|
||||
if (this.code.length < 5) {
|
||||
this.code += number;
|
||||
}
|
||||
}
|
||||
if (this.code.length === 5) {
|
||||
this.inout_disable = true
|
||||
this.get_file()
|
||||
}
|
||||
},
|
||||
successUpload(response, file, fileList) {
|
||||
this.files.push(response.data[0])
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
@@ -0,0 +1,121 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
||||
<!-- 引入组件库 -->
|
||||
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||||
<title>寄件箱-口令传送箱</title>
|
||||
<style>
|
||||
.el-upload-dragger {
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="text-align: center;height: 100vh">
|
||||
<el-row style="width:400px;margin: auto">
|
||||
<el-col :span="24" style="margin: 1rem 0">
|
||||
<el-card>
|
||||
<el-upload
|
||||
drag
|
||||
action=""
|
||||
multiple
|
||||
:on-success="successUpload"
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖、粘贴到此处,或<em>点击上传</em>,24h后删除</div>
|
||||
<div class="el-upload__tip" slot="tip">
|
||||
<a href="/">
|
||||
<el-button>去取件</el-button>
|
||||
</a>
|
||||
<el-button @click="drawer=true">文件箱</el-button>
|
||||
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-drawer
|
||||
title="文件库"
|
||||
:visible.sync="drawer"
|
||||
direction="btt"
|
||||
size="50%">
|
||||
<el-card>
|
||||
<el-empty v-if="files.length===0" description="请上传文件"></el-empty>
|
||||
<el-card style="margin-top: 0.2rem" v-for="file in files" :key="file.code">
|
||||
<el-row>
|
||||
<el-col :span="24" style="line-height: 45px">
|
||||
${ file.name }
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
取件码:<h1 style="margin: 0;display: inline">${ file.code }</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</body>
|
||||
<!-- import Vue before Element -->
|
||||
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
|
||||
<!-- import JavaScript -->
|
||||
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||||
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
delimiters: ['${', '}'],
|
||||
data: function () {
|
||||
return {
|
||||
files: [],
|
||||
drawer: false
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
const that = this
|
||||
document.addEventListener('paste', function () {
|
||||
const items = event.clipboardData && event.clipboardData.items;
|
||||
if (items && items.length) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].kind === 'string') {
|
||||
if (items[i].type.match(/^text\/plain/)) {
|
||||
const FileData = new FormData();
|
||||
that.$message('剪切板文字正在上传,请稍等');
|
||||
items[i].getAsString(function (str) {
|
||||
FileData.append('text', str);
|
||||
axios.post('', FileData)
|
||||
.then(function (response) {
|
||||
that.$message({'message': response.data.msg, 'type': 'success'});
|
||||
that.files.push(response.data.data)
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message({'message': error.data.msg, 'type': 'error'});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const file = items[i].getAsFile();
|
||||
that.$message('剪切板文件正在上传,请稍等');
|
||||
const FileData = new FormData();
|
||||
FileData.append('file', file || '');
|
||||
axios.post('', FileData).then(async res => {
|
||||
that.files.push(res.data.data);
|
||||
that.$message({'message': res.data.msg, 'type': 'success'});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
successUpload(response, file, fileList) {
|
||||
this.files.push(response.data[0])
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user