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()