112 lines
2.8 KiB
Python
112 lines
2.8 KiB
Python
from flask import (
|
|
Flask,
|
|
request,
|
|
abort,
|
|
Response
|
|
)
|
|
from flask_cors import cross_origin
|
|
import os
|
|
from uuid import uuid4
|
|
import subprocess
|
|
import shutil
|
|
import io
|
|
from werkzeug.wsgi import FileWrapper
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
@app.route("/", methods=['POST'])
|
|
@cross_origin(expose_headers=["content-disposition"])
|
|
def upload_files():
|
|
project_id = str(uuid4())
|
|
|
|
main_file = get_and_save_file(request, "main-file", project_id)
|
|
|
|
if main_file is False:
|
|
abort(400)
|
|
|
|
project_folder = f"/data/build/{project_id}"
|
|
if not os.path.exists(project_folder):
|
|
os.makedirs(project_folder)
|
|
|
|
file_name = ".".join(main_file.split("/")[-1].split(".")[:-1])
|
|
result_file_path = f"{project_folder}/{file_name}.stl"
|
|
|
|
command = [
|
|
"openscad",
|
|
"-o", result_file_path
|
|
]
|
|
|
|
param_file = get_and_save_file(request, "param-file", project_id)
|
|
|
|
if param_file is not False:
|
|
command.extend(["-p", param_file])
|
|
|
|
keys = list(request.files.keys())
|
|
keys.remove("main-file")
|
|
|
|
try:
|
|
keys.remove("param-file")
|
|
except ValueError:
|
|
print("List does not contain value")
|
|
|
|
# Add other files
|
|
for key in keys:
|
|
get_and_save_file(request, key, project_id)
|
|
|
|
# Add main file at the end of the command and run it!
|
|
command.append(main_file)
|
|
subprocess.run(command, cwd=project_folder)
|
|
|
|
# Store the file in memory so it can be removed but still served
|
|
return_data = io.BytesIO()
|
|
with open(result_file_path, 'rb') as fo:
|
|
return_data.write(fo.read())
|
|
# (after writing, cursor will be at last byte, so move it to start)
|
|
return_data.seek(0)
|
|
|
|
# Remove the files
|
|
shutil.rmtree(f"/data/upload/{project_id}")
|
|
os.remove(result_file_path)
|
|
|
|
# Wrap the data in a FileWrapper for uWSGI and set its headers
|
|
w = FileWrapper(return_data)
|
|
headers = {
|
|
'Content-Disposition': f"attachment; filename='{file_name}.stl'"
|
|
}
|
|
|
|
# Send the generated file
|
|
return Response(w, mimetype="application/stl",
|
|
direct_passthrough=True, headers=headers)
|
|
|
|
|
|
def get_and_save_file(request, fileId, projectId):
|
|
# Check if the file we're requesting is in the request
|
|
if fileId not in request.files:
|
|
return False
|
|
|
|
project_path = os.path.join("/data/upload", projectId)
|
|
|
|
# Check if folder for project exist, create it if it doesn't exist
|
|
if not os.path.exists(project_path):
|
|
os.makedirs(project_path)
|
|
|
|
f = request.files[fileId]
|
|
|
|
# Check if the uploaded file is a file or an empty field
|
|
if f.filename == "":
|
|
return False
|
|
|
|
file_path = os.path.join(project_path, f.filename)
|
|
|
|
# Check if the file exists already
|
|
if os.path.exists(file_path):
|
|
return False
|
|
|
|
f.save(file_path)
|
|
return file_path
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run()
|