view odfcast/convert.py @ 42:6d511e93a331

Return requested format when an error has occured Introduce ErrorResponse class which returns the error in the format as requested.
author Björn Ricks <bjoern.ricks@intevation.de>
date Wed, 22 Oct 2014 14:38:31 +0200
parents a1100ec32be2
children e99cbb47eafb
line wrap: on
line source
# -*- coding: utf-8 -*-

import logging
import tempfile

from flask import request, Response, json, render_template
from flask.views import MethodView

from py3o.template import Template

from PyPDF2 import PdfFileMerger

log = logging.getLogger(__name__)

ALLOWED_FORMATS = ["pdf", "doc", "docx", "odt"]

PDF_MIMETYPE = "application/pdf"

MIMETYPES = {
    "odt": "application/vnd.oasis.opendocument.text",
    "doc": "application/msword",
    "docx": "application/vnd.openxmlformats-officedocument"
    ".wordprocessingml.document",
    "pdf": PDF_MIMETYPE,
}

DEFAULT_MIMETYPE = "application/octet-stream"


class ErrorResponse(object):

    def __init__(self, title, details="", html_error_code=500):
        self.title = title
        self.details = details
        self.html_error_code = html_error_code

    def __call__(self):
        if self.is_wants_json():
            return self.json()
        else:
            return self.html()

    def json(self):
        return json.dumps({
            "error": self.title,
            "details": self.details
        }), self.html_error_code

    def html(self):
        return self.title, self.html_error_code

    def is_wants_json(self):
        best = request.accept_mimetypes.best_match(['application/json',
                                                    'text/html'])
        return best == 'application/json' and \
            request.accept_mimetypes[best] > \
            request.accept_mimetypes['text/html']


class ConvertView(MethodView):

    def __init__(self, pyuno_driver_name="", hostname="localhost", port=2001):
        driver_module = self._load_driver_module(pyuno_driver_name)
        self.convertor = driver_module.Convertor(hostname, port)

    def _load_driver_module(self, pyuno_driver_name):
        return __import__(pyuno_driver_name, globals(), locals(),
                          ["Convertor"])

    def is_format_supported(self, fformat):
        return fformat and fformat.lower() in ALLOWED_FORMATS

    def post(self):
        ffile = request.files['file']
        if not ffile.filename:
            error = ErrorResponse("Please upload a file for conversion",
                                  html_error_code=401)
            return error()

        fformat = request.form['format']
        if not self.is_format_supported(fformat):
            error = ErrorResponse("Format %s not allowed" % fformat,
                                  html_error_code=401)
            return error()

        datadict = self.get_datadict()

        mimetype = self.get_mimetype_for_format(fformat)

        outfile = self.save_form_file(ffile)

        if datadict:
            try:
                tfile = tempfile.NamedTemporaryFile()
                t = Template(outfile, tfile, ignore_undefined_variables=True)
                t.render(datadict)
                outfile.close()
                outfile = tfile
            except Exception, e:
                log.exception("Template error")
                error = ErrorResponse(
                    "Template error", details=str(e), html_error_code=500)
                return error()

        if fformat != "odt":
            try:
                outfile = self.convert(outfile, fformat)
            except Exception, e:
                log.exception("Conversion error")
                error = ErrorResponse(
                    "Conversion error", details=str(e), html_error_code=500)
                return error()

        return Response(outfile, mimetype=mimetype)

    def get(self):
        return render_template("convert.html")

    def save_form_file(self, infile):
        outfile = tempfile.NamedTemporaryFile()
        infile.save(outfile)
        infile.close()
        outfile.seek(0)
        return outfile

    def convert(self, infile, fformat):
        outfile = tempfile.NamedTemporaryFile()

        self.convertor.convert(infile.name, outfile.name, fformat)

        infile.close()
        return outfile

    def get_mimetype_for_format(self, fformat):
        return MIMETYPES.get(fformat, DEFAULT_MIMETYPE)

    def get_datadict(self):
        vars = request.form.get('datadict')
        if not vars:
            return None
        return json.loads(vars)


class MergeView(MethodView):

    def get(self):
        return render_template("merge.html")

    def post(self):
        merger = PdfFileMerger()
        ffiles = request.files.getlist('files')

        for ffile in ffiles:
            merger.append(ffile)

        outfile = tempfile.NamedTemporaryFile()

        merger.write(outfile.name)

        merger.close()
        return Response(outfile, mimetype=PDF_MIMETYPE)


class TemplateView(MethodView):

    template_name = ""

    def __init__(self, template_name=None):
        if template_name:
            self.template_name = template_name

    def get_template_name(self):
        return self.template_name

    def get(self):
        return render_template(self.get_template_name())
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)