argos/docsbox-master/docsbox/docs/views.py

94 lines
3.8 KiB
Python

import ujson
import datetime
from magic import Magic
from tempfile import NamedTemporaryFile
from flask import request
from flask_restful import Resource, abort
from docsbox import app, rq
from docsbox.docs.tasks import remove_file, process_document
class DocumentView(Resource):
def get(self, task_id):
"""
Returns information about task status.
"""
queue = rq.get_queue()
task = queue.fetch_job(task_id)
if task:
return {
"id": task.id,
"status": task.status,
"result_url": task.result
}
else:
return abort(404, message="Unknown task_id")
class DocumentCreateView(Resource):
def post(self):
"""
Recieves file and options, checks file mimetype,
validates options and creates converting task
"""
if "file" not in request.files:
return abort(400, message="file field is required")
else:
with NamedTemporaryFile(delete=False, prefix=app.config["MEDIA_PATH"]) as tmp_file:
request.files["file"].save(tmp_file)
tmp_file.flush()
tmp_file.close()
remove_file.schedule(
datetime.timedelta(seconds=app.config["ORIGINAL_FILE_TTL"])
, tmp_file.name)
with Magic() as magic: # detect mimetype
mimetype = magic.from_file(tmp_file.name)
if mimetype not in app.config["SUPPORTED_MIMETYPES"]:
return abort(400, message="Not supported mimetype: '{0}'".format(mimetype))
options = request.form.get("options", None)
if options: # options validation
options = ujson.loads(options)
formats = options.get("formats", None)
if not isinstance(formats, list) or not formats:
return abort(400, message="Invalid 'formats' value")
else:
for fmt in formats:
supported = (fmt in app.config["SUPPORTED_MIMETYPES"][mimetype]["formats"])
if not supported:
message = "'{0}' mimetype can't be converted to '{1}'"
return abort(400, message=message.format(mimetype, fmt))
thumbnails = options.get("thumbnails", None)
if thumbnails:
if not isinstance(thumbnails, dict):
return abort(400, message="Invalid 'thumbnails' value")
else:
thumbnails_size = thumbnails.get("size", None)
if not isinstance(thumbnails_size, str) or not thumbnails_size:
return abort(400, message="Invalid 'size' value")
else:
try:
(width, height) = map(int, thumbnails_size.split("x"))
except ValueError:
return abort(400, message="Invalid 'size' value")
else:
options["thumbnails"]["size"] = (width, height)
else:
if mimetype == "application/pdf":
options = {
"formats": ["html"]
}
else:
options = app.config["DEFAULT_OPTIONS"]
task = process_document.queue(tmp_file.name, options, {
"mimetype": mimetype,
})
return {
"id": task.id,
"status": task.status,
}