1

ユーザーがファイルをアップロードできるフラスコベースの Web アプリがあります。ファイルは mysql データベースに保存されます。

これは、ファイルが約 16Mb より大きくなるまで正常に機能します。挿入は次のように失敗します。

File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1518, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1506, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1504, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1264, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1262, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1248, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/<redacted>/access_control.py", line 15, in decorated_function
    return f(*args, **kwargs)
  File "/<redacted>/views/files.py", line 48, in upload
    VALUES (%s, %s, %s, %s, %s)""", file_details)
  File "/<redacted>/database.py", line 66, in query
    cursor.execute(sql, values)
  File "/usr/local/lib/python2.7/dist-packages/pymysql/cursors.py", line 262, in execute
    result = super(DictCursor, self).execute(query, args)
  File "/usr/local/lib/python2.7/dist-packages/pymysql/cursors.py", line 117, in execute
    self.errorhandler(self, exc, value)
  File "/usr/local/lib/python2.7/dist-packages/pymysql/connections.py", line 187, in defaulterrorhandler
    raise Error(errorclass, errorvalue)
Error: (<class 'socket.error'>, error(32, 'Broken pipe'))

ファイルサイズが mySQL の設定と一致しているmax_allowed_packetように見えたときに興奮したので、変更してmy.cnf再起動しましたが、役に立ちませんでした。(show variables like 'max_allowed_packet'は 150M の新しい値を示します)

ファイルは間違いなくサーバーにアップロードされます。挿入メソッドにコードを挿入して、クエリを実行する前にファイルをディスクに書き込み、ファイルは問題ありませんでした。

BLOB が挿入されるフィールドは longblob です。挿入を担当するコードは次のとおりです。

@mod.route('/file/upload', methods=['POST'])
@login_required
def upload():
    filename = request.files['file'].filename
    mime_type = request.files['file'].mimetype
    #filesize = request.files['file'].content_length
    file = request.files['file'].stream.read()

    if mime_type[:5] == 'image':
        file = resize_image_to_width(file, 1024)

    filesize = len(file)
    if filesize == 0:
        return ""

    if not request.form['file_id']:
        file_details = (filename, file, mime_type, filesize, session['user']['user_id'])
        file_id = database.query("""INSERT INTO files (filename, file, mime_type, filesize, owner)
                                      VALUES (%s, %s, %s, %s, %s)""", file_details)
    else:
        file_details = (filename, file, mime_type, filesize, request.form['file_id'])

        file_id = database.query("""UPDATE files 
                                    SET 
                                        filename=%s, 
                                        file=%s, 
                                        mime_type=%s, 
                                        filesize=%s 
                                    WHERE file_id=%s""", file_details)
    return "upload complete"

私は今、少し途方に暮れています.1週間ほど前に、ファイルをセクションに挿入する必要があることを示唆するものをいくつか見つけましたが、今は見つけることができません(実際の仕事に気を取られました! )そして、それをチャンクに挿入する方法がわかりません。

これについて何か助けていただければ幸いです。

4

2 に答える 2

0

これは別のアプローチです。LOAD_FILE関数を使用して、ファイルを blob 列に読み込みます。

UPDATE t SET blob_col=LOAD_FILE('/tmp/image.png') WHERE id=1;

これは、あなたが持っていた 16MB の制限に直面するべきではありません。バイナリ エンコーディングの問題に直面した場合は、python を使用して画像を 16 進形式で保存し、UNHEXを使用して生のバイナリ形式に安全にデコードすることができます。

UPDATE t SET blob_col=UNHEX(LOAD_FILE('/tmp/image.png.hex')) WHERE id=1;

ただし、どちらのオプションでも、Web サーバーが同じサーバー上にある場合は、MySQL サーバーのファイルシステムにファイルを保存する必要があります。 .

于 2012-11-14T14:32:07.073 に答える
0

最初に、ファイルを挿入するのに安全なサイズのブロックにチャンクします。この場合、10MB にすることができます。これを行うには、その回答でチャンク機能を使用できます。次に、データの最初のチャンクを挿入し、追加のチャンクをその BLOB に連結する一連の更新を行います。その部分を行うには、update を使用して BLOB データを BLOB 列に追加/連結することに関する質問を確認してください。.

于 2012-11-14T10:37:51.843 に答える