added splitted file uploader and joiner. its still a bit beta
This commit is contained in:
157
code/app.py
157
code/app.py
@@ -4,14 +4,15 @@
|
|||||||
import os,sys,time,stat
|
import os,sys,time,stat
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import Flask, render_template, jsonify, current_app, \
|
from flask import Flask, render_template, jsonify, current_app, Response, \
|
||||||
redirect, url_for, request, g, session, send_file, send_from_directory
|
redirect, url_for, request, g, session, send_file, send_from_directory
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
import hashlib
|
import hashlib
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from multiprocessing import Process
|
||||||
from revprox import ReverseProxied
|
from revprox import ReverseProxied
|
||||||
|
|
||||||
__FLEES_VERSION__ = "20180221.0"
|
__FLEES_VERSION__ = "20180224.0b"
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object(__name__)
|
app.config.from_object(__name__)
|
||||||
# Read config from json !
|
# Read config from json !
|
||||||
@@ -90,7 +91,7 @@ def upload(name = None, password = None):
|
|||||||
if not ok:
|
if not ok:
|
||||||
return share
|
return share
|
||||||
if not get_or_none(share,'upload') == True:
|
if not get_or_none(share,'upload') == True:
|
||||||
return "Upload not allowed",400
|
return "Upload not allowed\n",400
|
||||||
if file:
|
if file:
|
||||||
filename = os.path.join(
|
filename = os.path.join(
|
||||||
share['path'],
|
share['path'],
|
||||||
@@ -115,7 +116,53 @@ def upload(name = None, password = None):
|
|||||||
return redirect(url_for('list_view',name=name))
|
return redirect(url_for('list_view',name=name))
|
||||||
return "File uploaded\n", 200
|
return "File uploaded\n", 200
|
||||||
else:
|
else:
|
||||||
return "Use the 'file' variable to upload",400
|
return "Use the 'file' variable to upload\n",400
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/upload_join/<name>/<password>', methods=['POST'])
|
||||||
|
def upload_join_splitted(name, password):
|
||||||
|
if request.method == 'POST':
|
||||||
|
session[name] = password
|
||||||
|
(ok,share) = get_share(name)
|
||||||
|
if not ok:
|
||||||
|
return share
|
||||||
|
if not get_or_none(share,'upload') == True:
|
||||||
|
return "Upload not allowed",400
|
||||||
|
if not 'filename' in request.form:
|
||||||
|
return "No filename given", 400
|
||||||
|
parts = []
|
||||||
|
for part in range(100):
|
||||||
|
filename = os.path.join(
|
||||||
|
share['path'],
|
||||||
|
"%s.part.%02d"%(
|
||||||
|
request.form['filename'],
|
||||||
|
part
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if os.path.exists(filename):
|
||||||
|
parts.append(filename)
|
||||||
|
part_existed = part
|
||||||
|
if len(parts) == 0:
|
||||||
|
return "Invalid partial filename\n", 400
|
||||||
|
if not len(parts) == part_existed + 1:
|
||||||
|
return "Parts missing\n", 400
|
||||||
|
target_name = os.path.join(
|
||||||
|
share['path'],
|
||||||
|
request.form['filename']
|
||||||
|
)
|
||||||
|
if get_or_none(share, 'overwrite') == False:
|
||||||
|
if os.path.exists(target_name):
|
||||||
|
file_versionize(target_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
begin = uploadJoiner(target_name, parts)
|
||||||
|
except:
|
||||||
|
return "Joining failed\n", 400
|
||||||
|
return "Joining started\n", 200
|
||||||
|
#~ return Response(joiner(target_name, parts), mimetype="text/plain", content_type="text/event-stream")
|
||||||
|
|
||||||
|
#~ return "%d parts joined"%(len(parts),), 200
|
||||||
|
|
||||||
|
|
||||||
@app.route('/send/<name>', methods=['GET'])
|
@app.route('/send/<name>', methods=['GET'])
|
||||||
def send(name):
|
def send(name):
|
||||||
@@ -399,6 +446,84 @@ get_file() {
|
|||||||
return script
|
return script
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/script/upload_split/<name>/<password>', methods=['GET'])
|
||||||
|
def script_upload_split(name = None, password = None):
|
||||||
|
session[name] = password
|
||||||
|
(ok,share) = get_share(name)
|
||||||
|
if not ok:
|
||||||
|
return share
|
||||||
|
if not get_or_none(share,'upload') == True:
|
||||||
|
return "Upload not allowed",400
|
||||||
|
return """#!/bin/bash
|
||||||
|
test -n "$1" || {
|
||||||
|
echo "First argument is split size in megabytes, add files to upload as next arguments"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
test -n "$2" || {
|
||||||
|
echo "Add files to upload as argument"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
CAT=$( which cat )
|
||||||
|
which pv &> /dev/null && CAT=$( which pv )
|
||||||
|
ROOTURL="%s"
|
||||||
|
SHARE="%s"
|
||||||
|
TOKEN="%s"
|
||||||
|
MAXBYTES=$(( $1 * 1024 * 1024 ))
|
||||||
|
shift 1
|
||||||
|
|
||||||
|
send_file() {
|
||||||
|
$CAT "$file_name" | split -d -b $MAXBYTES \
|
||||||
|
--filter="curl -F \\"file=@-;filename=\${FILE}\\" ${ROOTURL}upload/${SHARE}/${TOKEN}" \
|
||||||
|
- "$base_name.part."
|
||||||
|
curl -F "filename=$base_name" ${ROOTURL}upload_join/${SHARE}/${TOKEN}
|
||||||
|
}
|
||||||
|
send_folder() {
|
||||||
|
which pv &> /dev/null && printf -v dusize -- "--size %%dk" $( du -s -k "$file_name" | cut -f1 )
|
||||||
|
tar c "$file_name" | $CAT $dusize - | split -d -b $MAXBYTES \
|
||||||
|
--filter="curl -F \\"file=@-;filename=\${FILE}\\" ${ROOTURL}upload/${SHARE}/${TOKEN}" \
|
||||||
|
- "$base_name.tgz.part."
|
||||||
|
curl -F "filename=$base_name.tgz" ${ROOTURL}upload_join/${SHARE}/${TOKEN}
|
||||||
|
}
|
||||||
|
|
||||||
|
for file_name in "$@"; do
|
||||||
|
base_name=$( basename "$file_name" )
|
||||||
|
test -f "$file_name" && {
|
||||||
|
printf "Sending file: %%s\n" "$file_name"
|
||||||
|
send_file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
test -d "$file_name" && {
|
||||||
|
printf "Sending folder: %%s\n" "$file_name"
|
||||||
|
send_folder
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
done
|
||||||
|
"""%(
|
||||||
|
request.url_root,
|
||||||
|
name,
|
||||||
|
password
|
||||||
|
)
|
||||||
|
|
||||||
|
class uploadJoiner:
|
||||||
|
|
||||||
|
def __init__(self, target_name, parts):
|
||||||
|
self.target_name = target_name
|
||||||
|
self.parts = parts
|
||||||
|
self.chunk_size = 10 * 1024 * 1024
|
||||||
|
p = Process(target=self.run, args=())
|
||||||
|
p.daemon = True
|
||||||
|
p.start()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
with open(self.target_name,'wb') as writer:
|
||||||
|
for part in self.parts:
|
||||||
|
with open(part,'rb') as reader:
|
||||||
|
for chunk in iter(lambda: reader.read(self.chunk_size), b""):
|
||||||
|
writer.write(chunk)
|
||||||
|
set_rights(self.target_name)
|
||||||
|
for part in self.parts:
|
||||||
|
os.remove(part)
|
||||||
|
|
||||||
def file_stat(filename):
|
def file_stat(filename):
|
||||||
s = os.stat(filename)
|
s = os.stat(filename)
|
||||||
return {
|
return {
|
||||||
@@ -426,17 +551,23 @@ def file_date_human(num):
|
|||||||
).strftime(app.config['DATE_FORMAT'])
|
).strftime(app.config['DATE_FORMAT'])
|
||||||
|
|
||||||
def file_versionize(filename):
|
def file_versionize(filename):
|
||||||
""" Move file to old version """
|
""" Move file to versioned with integer """
|
||||||
stats = file_stat(filename)
|
stats = file_stat(filename)
|
||||||
basename, extension = os.path.splitext(stats['name'])
|
basename, extension = os.path.splitext(stats['name'])
|
||||||
new_name = os.path.join(
|
version = 1
|
||||||
os.path.dirname(filename),
|
while True:
|
||||||
secure_filename("%s.%s%s"%(
|
new_name = os.path.join(
|
||||||
basename,
|
os.path.dirname(filename),
|
||||||
stats['mtime'],
|
secure_filename("%s.v%d%s"%(
|
||||||
extension
|
basename,
|
||||||
))
|
version,
|
||||||
)
|
extension
|
||||||
|
))
|
||||||
|
)
|
||||||
|
if os.path.exists(new_name):
|
||||||
|
version += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
os.rename(filename,new_name)
|
os.rename(filename,new_name)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -151,3 +151,7 @@ tr:nth-child(odd) {
|
|||||||
#progress.failure {
|
#progress.failure {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sortarrow {
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user