first commit
commit
abf7741b16
|
@ -0,0 +1,83 @@
|
||||||
|
# Transfert
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
I used to transfert big files using Jirafeau. But I decided to create my own tool.
|
||||||
|
|
||||||
|
I wanted :
|
||||||
|
- Something modern and safer than PHP
|
||||||
|
- with QRcode possibility
|
||||||
|
- No database
|
||||||
|
- Clean expired files automatically
|
||||||
|
- Manage single Download
|
||||||
|
- SSL Connexion
|
||||||
|
|
||||||
|
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/) [![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) [![AGPL License](https://img.shields.io/badge/license-AGPL-blue.svg)](http://www.gnu.org/licenses/agpl-3.0)
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
```sh
|
||||||
|
|
||||||
|
Ubuntu/Debian:
|
||||||
|
|
||||||
|
git clone https://git.nerkdesign.com/pporcheret/Transfert.git
|
||||||
|
cd ./Transfert/
|
||||||
|
mkdir storage
|
||||||
|
apt install python3 python3-pip
|
||||||
|
pip3 install -r requirement.txt
|
||||||
|
|
||||||
|
Redhat:
|
||||||
|
|
||||||
|
git clone https://git.nerkdesign.com/pporcheret/Transfert.git
|
||||||
|
cd ./Transfert/
|
||||||
|
mkdir storage
|
||||||
|
yum install python3 python3-pip
|
||||||
|
pip3 install -r requirement.txt
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Start
|
||||||
|
|
||||||
|
python3 app.py
|
||||||
|
|
||||||
|
Use your browser to go to :
|
||||||
|
```sh
|
||||||
|
https://{{IP}}:5006
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
You can edit the Flask port/host :
|
||||||
|
```sh
|
||||||
|
flask_port=5006
|
||||||
|
flask_host='0.0.0.0'
|
||||||
|
flask_thread=True
|
||||||
|
flask_debug=False
|
||||||
|
```
|
||||||
|
The size of the random link :
|
||||||
|
```sh
|
||||||
|
random_size = 12
|
||||||
|
```
|
||||||
|
The storage location of your files :
|
||||||
|
```sh
|
||||||
|
path = os.path.dirname(__file__)
|
||||||
|
storage_path= path+'/storage/'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Login
|
||||||
|
|
||||||
|
|
||||||
|
Be carefull !!
|
||||||
|
By default, the authentification is PAM.
|
||||||
|
This PAM auth is based on the library [simplepam](https://github.com/leonnnn/python3-simplepam).
|
||||||
|
This means that by default, the allowed users, are the user in the server.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
![ScreenShot](./images/screen0.png)
|
||||||
|
![ScreenShot2](./images/screen1.png)
|
||||||
|
![ScreenShot2](./images/screen2.png)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
|
||||||
|
#!/usr/bin/python3
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import string
|
||||||
|
import random
|
||||||
|
import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
from flask_qrcode import QRcode
|
||||||
|
from werkzeug.utils import secure_filename
|
||||||
|
from flask import Flask, render_template, Response, request, redirect, url_for, session, escape, send_from_directory, send_file, after_this_request
|
||||||
|
from flask_fontawesome import FontAwesome
|
||||||
|
from simplepam import authenticate
|
||||||
|
from flask_navigation import Navigation
|
||||||
|
from flask_dropzone import Dropzone
|
||||||
|
|
||||||
|
##Variables
|
||||||
|
#Flask config
|
||||||
|
flask_port=5006
|
||||||
|
flask_host='0.0.0.0'
|
||||||
|
flask_thread=True
|
||||||
|
flask_debug=False
|
||||||
|
#Other
|
||||||
|
random_size = 12
|
||||||
|
|
||||||
|
#path base for service lauch
|
||||||
|
path = os.path.dirname(__file__)
|
||||||
|
storage_path= path+'/storage/'
|
||||||
|
|
||||||
|
#Flask init
|
||||||
|
app = Flask(__name__,static_url_path='',static_folder='static',template_folder='templates')
|
||||||
|
|
||||||
|
#Init QRcode
|
||||||
|
QRcode(app)
|
||||||
|
|
||||||
|
#Init FontAwsome
|
||||||
|
fa = FontAwesome(app)
|
||||||
|
|
||||||
|
#Init Nav
|
||||||
|
nav = Navigation(app)
|
||||||
|
|
||||||
|
nav.Bar('top', [
|
||||||
|
nav.Item('Index', 'index'),
|
||||||
|
nav.Item('Upload', 'uploads'),
|
||||||
|
])
|
||||||
|
|
||||||
|
#DropZone
|
||||||
|
app.config.update(
|
||||||
|
UPLOADED_PATH= storage_path)
|
||||||
|
dropzone = Dropzone(app)
|
||||||
|
|
||||||
|
##Functions
|
||||||
|
def today_format():
|
||||||
|
x = datetime.datetime.now()
|
||||||
|
return x.strftime("%d%m%y%H%M%S")
|
||||||
|
|
||||||
|
def time_end(date_up,retention):
|
||||||
|
retention = int(retention)
|
||||||
|
tdate = datetime.datetime.strptime(date_up, '%d%m%y%H%M%S')
|
||||||
|
end_date = tdate + timedelta(hours = retention)
|
||||||
|
end_date = end_date.strftime("%d%m%y%H%M%S")
|
||||||
|
return end_date
|
||||||
|
|
||||||
|
def del_expired_files():
|
||||||
|
files=os.listdir(storage_path)
|
||||||
|
for file in files:
|
||||||
|
list_file=file.split("_")
|
||||||
|
retention = ''.join(list_file[-2:-1])
|
||||||
|
if retention != '0':
|
||||||
|
date_up = ''.join(list_file[-3:-2])
|
||||||
|
end_date = time_end(date_up,retention)
|
||||||
|
end_date = datetime.datetime.strptime(end_date,"%d%m%y%H%M%S")
|
||||||
|
actual_date = datetime.datetime.now()
|
||||||
|
if end_date < actual_date:
|
||||||
|
if os.path.exists(storage_path+file):
|
||||||
|
os.remove(storage_path+file)
|
||||||
|
|
||||||
|
def random_link():
|
||||||
|
res = ''.join(random.choices(string.ascii_letters+string.digits, k=random_size))
|
||||||
|
return res
|
||||||
|
|
||||||
|
def list_files():
|
||||||
|
out_files=[]
|
||||||
|
files=os.listdir(storage_path)
|
||||||
|
for file in files:
|
||||||
|
middle=[]
|
||||||
|
list_file=file.split("_")
|
||||||
|
singled = ''.join(list_file[-1:])
|
||||||
|
retention=''.join(list_file[-2:-1])
|
||||||
|
date_up=''.join(list_file[-3:-2])
|
||||||
|
link=''.join(list_file[-4:-3])
|
||||||
|
list_file_name=list_file[:-4]
|
||||||
|
list_file_name='_'.join(list_file_name)
|
||||||
|
end_date = time_end(date_up,retention)
|
||||||
|
middle.append(list_file_name)
|
||||||
|
middle.append(retention)
|
||||||
|
middle.append(date_up)
|
||||||
|
middle.append(link)
|
||||||
|
middle.append(end_date)
|
||||||
|
middle.append(request.url_root+"download/"+link)
|
||||||
|
middle.append(singled)
|
||||||
|
out_files.append(middle)
|
||||||
|
return out_files
|
||||||
|
|
||||||
|
##Pages
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
if 'username' in session:
|
||||||
|
del_expired_files()
|
||||||
|
return render_template('index.html',loguser=session['username'],listdir=list_files())
|
||||||
|
return render_template('login.html',title="Login")
|
||||||
|
|
||||||
|
@app.route('/down/<link>')
|
||||||
|
def down(link):
|
||||||
|
del_expired_files()
|
||||||
|
files=list_files()
|
||||||
|
for file in files:
|
||||||
|
if link == file[3]:
|
||||||
|
filename=file[0]+"_"+file[3]+"_"+file[2]+"_"+file[1]+"_"+file[6]
|
||||||
|
if file[6] == 'YES':
|
||||||
|
@after_this_request
|
||||||
|
def remove_file(reponse):
|
||||||
|
os.remove(storage_path+filename)
|
||||||
|
return reponse
|
||||||
|
return send_file(storage_path+filename, download_name=secure_filename(file[0]))
|
||||||
|
return render_template('nodown.html',title='No Download')
|
||||||
|
|
||||||
|
@app.route('/download/<link>')
|
||||||
|
def download(link):
|
||||||
|
del_expired_files()
|
||||||
|
files=list_files()
|
||||||
|
for file in files:
|
||||||
|
if link == file[3]:
|
||||||
|
filename=file[0]
|
||||||
|
url_todl=request.url_root+"down/"+link
|
||||||
|
return render_template('download.html',title="Download",filename=filename,url_todl=url_todl,qrcode=QRcode.qrcode(url_todl, mode="base64"))
|
||||||
|
|
||||||
|
@app.route('/uploads')
|
||||||
|
def uploads():
|
||||||
|
if 'username' in session:
|
||||||
|
del_expired_files()
|
||||||
|
return render_template('upload.html',loguser=session['username'])
|
||||||
|
return render_template('login.html',title="Login")
|
||||||
|
|
||||||
|
@app.route('/upload', methods = ['POST'])
|
||||||
|
def upload():
|
||||||
|
del_expired_files()
|
||||||
|
retention = request.form['retention']
|
||||||
|
r = ['on']
|
||||||
|
if request.form.getlist('uniqd') == r:
|
||||||
|
singled = 'YES'
|
||||||
|
else:
|
||||||
|
singled = 'NO'
|
||||||
|
my_files = request.files
|
||||||
|
for item in my_files:
|
||||||
|
uploaded_file = my_files.get(item)
|
||||||
|
uploaded_file.filename = secure_filename(uploaded_file.filename)
|
||||||
|
link = random_link()
|
||||||
|
today = today_format()
|
||||||
|
print(uploaded_file.filename+"_"+link+"_"+today+"_"+retention+"_"+singled)
|
||||||
|
uploaded_file.save(os.path.join(app.config['UPLOADED_PATH'],uploaded_file.filename+"_"+link+"_"+today+"_"+retention+"_"+singled))
|
||||||
|
return render_template('upload.html',title="Upload")
|
||||||
|
|
||||||
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
username = request.form['username']
|
||||||
|
if username == 'root':
|
||||||
|
resultats='<p id="alert" style="color:red">Root not allowed </p>'
|
||||||
|
return render_template('login.html', alertmessage=resultats)
|
||||||
|
else:
|
||||||
|
password = request.form['password']
|
||||||
|
if authenticate(str(username), str(password)):
|
||||||
|
session['username'] = request.form['username']
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
else:
|
||||||
|
resultats='<p id="alert" style="color:red">Invalid Username/Password ! </p>'
|
||||||
|
return render_template('login.html', alertmessage=resultats)
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.pop('username', None)
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host=flask_host, port=flask_port, threaded=flask_thread, debug=flask_debug, ssl_context='adhoc')
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
flask_qrcode
|
||||||
|
flask
|
||||||
|
flask_fontawesome
|
||||||
|
simplepam
|
||||||
|
flask_navigation
|
||||||
|
flask_dropzone
|
||||||
|
pyopenssl
|
|
@ -0,0 +1,113 @@
|
||||||
|
body {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 300;
|
||||||
|
font-family: helvetica, arial, verdana, sans-serif;
|
||||||
|
text-align:center;
|
||||||
|
min-height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-underline{
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropzone {
|
||||||
|
box-shadow: 0px 2px 20px 0px #f2f2f2;
|
||||||
|
border: 1px dashed #c0ccda;
|
||||||
|
padding: 60x;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #fbfdff;
|
||||||
|
margin-left: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tacts {
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.qard {
|
||||||
|
text-align:center;
|
||||||
|
width:100%;
|
||||||
|
padding:20px;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.login {
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
|
||||||
|
width:300px;
|
||||||
|
height:400px;
|
||||||
|
padding:50px;
|
||||||
|
text-align:center;
|
||||||
|
margin:auto;
|
||||||
|
background-color:white;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
width:100px;
|
||||||
|
background: Transparent;
|
||||||
|
box-shadow: 0px 0.5px 1px rgba(0, 0, 0, 0.1), inset 0px 0.5px 0.5px rgba(255, 255, 255, 0.5), 0px 0px 0px 0.5px rgba(0, 0, 0, 0.12);
|
||||||
|
cursor: pointer;
|
||||||
|
margin:auto;
|
||||||
|
padding: 5px 5px;
|
||||||
|
}
|
||||||
|
select, option {
|
||||||
|
width: 243px;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
.logout {
|
||||||
|
text-align: right;
|
||||||
|
width:100%;
|
||||||
|
text-decoration:none;
|
||||||
|
height:33px;
|
||||||
|
}
|
||||||
|
.logout a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.logout ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #C0C0C0;
|
||||||
|
position: -webkit-sticky; /* Safari */
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
.logout li {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.logout li a {
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 14px 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout li a:hover {
|
||||||
|
background-color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout .active {
|
||||||
|
background-color: #336699;
|
||||||
|
}
|
||||||
|
.close {
|
||||||
|
color: #aaa;
|
||||||
|
float: right;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close:hover, .close:focus {
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||||
|
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
|
||||||
|
|
||||||
|
{{ fontawesome_css() }}
|
||||||
|
{{ dropzone.load_css() }}
|
||||||
|
{{ dropzone.style('border: 2px dashed #000; min-height: 200px;text-align:center;') }}
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
<br>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet" type="text/css">
|
||||||
|
<body>
|
||||||
|
<div id="content">
|
||||||
|
<center>
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% include 'base.html' %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<h5 class="display-8">Files to Download</h5>
|
||||||
|
<div style="padding:40px">
|
||||||
|
<div class="quard">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<br>
|
||||||
|
File name : {{ filename }}<br><br>
|
||||||
|
Direct URL : <a href="{{ url_todl }}">{{ url_todl }}</a><br><br>
|
||||||
|
<img src="{{ qrcode }}">
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</div></div></div></div>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ fontawesome_js() }}
|
||||||
|
<script
|
||||||
|
src="https://code.jquery.com/jquery-3.6.1.slim.min.js"
|
||||||
|
integrity="sha256-w8CvhFs7iHNVUtnSP0YKEg00p9Ih13rlL9zGqvLdePA="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,31 @@
|
||||||
|
{% include 'base.html' %}
|
||||||
|
{% block main %}
|
||||||
|
{% include 'menu.html' %}
|
||||||
|
<h5 class="display-8">Files list</h5>
|
||||||
|
<br>
|
||||||
|
<div style="padding:40px;">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>Retention (hours)</td>
|
||||||
|
<td>Upload date</td>
|
||||||
|
<td>Link</td>
|
||||||
|
<td>End Download Time</td>
|
||||||
|
<td>Download page</td>
|
||||||
|
<td>Single Download</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%for file in listdir %}
|
||||||
|
<tr>
|
||||||
|
{%for item in file %}
|
||||||
|
<td>{{ item }}</td>
|
||||||
|
{%endfor%}
|
||||||
|
</tr>
|
||||||
|
{%endfor%}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% include 'foot.html' %}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% include 'base.html' %}
|
||||||
|
{% block main %}
|
||||||
|
<div class="space"></div>
|
||||||
|
{{ alertmessage | safe }}
|
||||||
|
<br>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet" type="text/c>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Dosis' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Nunito' rel='stylesheet' type='text/css'>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<center>
|
||||||
|
<div class="space"></div>
|
||||||
|
<center>
|
||||||
|
<div class="login">
|
||||||
|
<h3>Login</h3>
|
||||||
|
<br><br>
|
||||||
|
<form action="/login" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="username" placeholder="Username" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button name="Login" type="submit" class="btn btn-info"><span class="fas fa-user"> Login</span></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% include 'foot.html' %}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{% block main %}
|
||||||
|
<div class="logout">
|
||||||
|
<ul>
|
||||||
|
{% for item in nav.top %}
|
||||||
|
<li class="{{ 'active' if item.is_active else '' }}">
|
||||||
|
<a href="{{ item.url }}">{{ item.label }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li style="float:right;">
|
||||||
|
<a href="logout"><span class="fas fa-user" style="display: inline;"></span> Logout</a>
|
||||||
|
</li>
|
||||||
|
<li style="float:right;">
|
||||||
|
<a href="javascript:window.location.href=window.location.href"><span class="fas fa-sync" style="display: inline;"></span></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% include 'base.html' %}
|
||||||
|
{% block main %}
|
||||||
|
<h5 class="display-8">No files to Download</h5>
|
||||||
|
<div style="padding:40px">
|
||||||
|
<div class="quard">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
Nothing to download, file missing or already deleted.<br>
|
||||||
|
Contact your sender if you think it's a mistake.
|
||||||
|
</div></div></div></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
{% include 'base.html' %}
|
||||||
|
{% include 'menu.html' %}
|
||||||
|
{% block main %}
|
||||||
|
{{ dropzone.load_js() }}
|
||||||
|
{{ dropzone.config() }}
|
||||||
|
<script type="text/javascript">
|
||||||
|
Dropzone.options.myDropzone = {
|
||||||
|
|
||||||
|
autoProcessQueue: false,
|
||||||
|
maxFilesize: 10240,
|
||||||
|
acceptedFiles: ".zip,.rar,.tar,.gz",
|
||||||
|
init: function() {
|
||||||
|
var submitButton = document.querySelector("#submit-all")
|
||||||
|
myDropzone = this; // closure
|
||||||
|
|
||||||
|
submitButton.addEventListener("click", function() {
|
||||||
|
myDropzone.processQueue(); // Tell Dropzone to process all queued files.
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("addedfile", function() {
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<h5 class="display-8">Upload</h5>
|
||||||
|
<div style="padding:40px">
|
||||||
|
<div class="quard">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="/upload" class="dropzone" id="my-dropzone" method="POST">
|
||||||
|
<label for="console_type">Retention</label>
|
||||||
|
<select id="retention" name="retention" class="form-control">
|
||||||
|
<option value="1">1 hour</option>
|
||||||
|
<option value="24">1 day</option>
|
||||||
|
<option value="168">1 week</option>
|
||||||
|
<option value="730">1 month</option>
|
||||||
|
<option value="0">Unlimited</option>
|
||||||
|
</select>
|
||||||
|
<div class="col-auto my-1">
|
||||||
|
<div class="custom-control custom-checkbox mr-sm-2">
|
||||||
|
<input type="checkbox" class="form-check-input" id="uniqd" name="uniqd">
|
||||||
|
<label for="uniqd">Single download </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<br>
|
||||||
|
<button id="submit-all" class="btn btn-info">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Avoid a Misalignment -->
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% include 'foot.html' %}
|
Loading…
Reference in New Issue