2017-09-17 14 views
0

私は非常に単純なアプリケーションを持っています。ユーザーは、Webフロントエンド経由でPostgresデータベースにpdfファイルをアップロードします。そのpdfは、pdfjs経由でブラウザに表示されます。Flask/postgres - PDFを表示PDFを使用

私の問題はエンコードされていることは間違いありませんが、私自身がこれに答えるために十分にエンコードを理解しているとは思いません。

マイモデル:

class Lesson(Base): 
    __tablename__ = 'lessons' 

    # Name of the lesson 
    lesson_order = db.Column(db.Enum(LessonIndexes), nullable=False) 
    name = db.Column(db.String(128), nullable=False) 
    summary = db.Column(db.String(500)) 
    lesson_plan_id = db.Column(db.Integer(), ForeignKey('lesson_plans.id'), nullable=False) 
    pdf = db.Column(db.LargeBinary()) 

マイコントローラー:

%PDF-1.4 
%���� 
1 0 obj 
<</Creator (Mozilla/5.0 \(Macintosh; Intel Mac OS X 10_12_6\) AppleWebKit/537.36 \(KHTML, like Gecko\) Chrome/60.0.3112.113 Safari/537.36) 
/Producer (Skia/PDF m60) 
/CreationDate (D:20170916222407+00'00') 
/ModDate (D:20170916222407+00'00')>> 
endobj 
2 0 obj 
<</Filter /FlateDecode 
/Length 1370>> stream 
x���ݎ�4��<������� qq$8�@%`aB�H�_�����T�E���ړ�c'�t�Z��[������}�{�I���@��� 

(etc...) 

私javasript(こんにちは、PDFJSから撮影した世界):

@mod_lp.route('/<lesson_plan_id>/create_lesson', methods=["POST"]) 
def create_lesson(lesson_plan_id): 
    form = LessonForm() 
    file = request.files['pdf'] # type: FileStorage 

    if form.validate_on_submit(): 
     file = request.files['pdf'] 
     lesson = Lesson(form.lesson_order.data, form.name.data, form.summary.data, lesson_plan_id, 
         pdf=file.read() # this line here 
         ) 
     db.session.add(lesson) 
     db.session.commit() 
    return redirect(url_for('lesson_plan.show', lesson_plan_id=lesson_plan_id)) 

これは、のようなものを見るためにデータを格納します:

var pdfString = "{{ pdf_data}}"; 
var pdfData = atob(pdfString); 
if (pdfData) { 
    var loadingTask = PDFJS.getDocument({data: pdfData}); 
    loadingTask.promise.then(function (pdf) { 
     console.log('PDF loaded'); 

     // Fetch the first page 
     var pageNumber = 1; 
     pdf.getPage(pageNumber).then(function (page) { 
      console.log('Page loaded'); 

      var scale = 1.5; 
      var viewport = page.getViewport(scale); 

      // Prepare canvas using PDF page dimensions 
      var canvas = document.getElementById('pdf-canvas'); 
      var context = canvas.getContext('2d'); 
      canvas.height = viewport.height; 
      canvas.width = viewport.width; 

      // Render PDF page into canvas context 
      var renderContext = { 
       canvasContext: context, 
       viewport: viewport 
      }; 
      var renderTask = page.render(renderContext); 
      renderTask.then(function() { 
       console.log('Page rendered'); 
      }); 
     }); 
    }, function (reason) { 
     // PDF loading error 
     console.error(reason); 
    }); 

私が持っている現在のエラーは、次のとおりです。私が試した

6:108 Uncaught DOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded. 

もの:

file.stream.getvalue() 

file.stream.getvalue().decode("latin-1") # for whatever reason, this was the only 'decode' that didn't throw an error 

file.stream.getvalue().decode("latin-1").encode() 

base64.b64encode(file.stream.getvalue().decode("latin-1").encode()) 

が、これらはすべて、さまざまな方法で失敗しました。 UPDATE:

私は私のテンプレートに、データベース内のバイナリデータを送信する場合:

pdf_data = lesson.pdf 

、その上にatobを呼び出すことを忘れる:

var pdfData = pdfString; 
     if (pdfData) { 
... 

私はこのエラーを取得します

Error: Invalid XRef stream header 
pdf.worker.js:340  at error (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:340:17) 
    at XRef_readXRef [as readXRef] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:20943:13) 
    at XRef_parse [as parse] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:20613:28) 
    at PDFDocument_setup [as setup] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:26445:17) 
    at PDFDocument_parse [as parse] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:26336:12) 
    at http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:36120:28 
    at Promise (<anonymous>) 
    at LocalPdfManager_ensure [as ensure] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:36115:14) 
    at LocalPdfManager.BasePdfManager_ensureDoc [as ensureDoc] (http://0.0.0.0:8080/static/js/pdfjs/build/pdf.worker.js:36067:19) 

答えて

1

atobは、base64でエンコードされた文字列を想定しています。私は、少なくともatobへの呼び出しを成功させるための基本的な例を得ました。確かにこれはあなたが見ている問題です。おそらくbase64でエンコードされたコンテンツをそのpostgresテーブルに保存するだけで、いつもデコードする必要はありません。 「source.pdf」はディスク上にあるサンプルpdfです。しかし、これをあなたのpostgresテーブルのデータと入れ替えることができます。

flask_app.py

from flask import Flask, request, render_template 
import base64 

app = Flask(__name__) 


@app.route("/testing", methods=["GET"]) 
def get_test_file(): 
    with open("source.pdf", "rb") as data_file: 
     data = data_file.read() 
    encoded_data = base64.b64encode(data).decode('utf-8') 
    return render_template("test.html", encoded_data=encoded_data) 

test.htmlという

<html> 
<head> 
</head> 
<body> 
    <script> 
    var encoded_data = '{{ encoded_data }}'; 
    var pdf_data = atob(encoded_data); 
    </script> 
</body> 
</html> 
+0

うわー!シンプルですが、私はそれを完全に逃しました。ありがとう!私はDB内のバイナリデータをストーリー化するのか、それともb64でエンコードされた文字列だけをストーリー化すべきですか – Jeff

+0

まったく問題ありません、ジェフ。正直なところ、データベースに保存することができますいずれかの方法は、種類の個人的な好みに依存します。 – Kyle