我有一个基于烧瓶的网络应用程序,允许用户上传文件。文件存储在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)
该文件肯定会上传到服务器,我将一些代码放入我的insert方法,在运行查询之前将文件写入磁盘并且文件正常。
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"
我现在有点不知所措,我确实在一周前找到了一些东西,建议将文件插入各个部分,但我现在找不到它(我被我分心了)实际的工作!)我不知道如何将其插入块中。
我真的很感激这方面的帮助!
答案 0 :(得分:0)
首先,您希望将文件分块为可插入的安全大小的块,在您的情况下,您可以将其设置为10MB。您可以使用该答案中的chunks function来执行此操作。然后插入第一块数据并执行一系列更新,将其他块连接到该blob上。要做到这一点,请查看append/concatenate BLOB data to a BLOB column using update?上的问题。
答案 1 :(得分:0)
这是另一种方法。使用LOAD_FILE函数将文件加载到blob列中。
UPDATE t SET blob_col=LOAD_FILE('/tmp/image.png') WHERE id=1;
这不应该面对您的16MB限制。如果您遇到任何二进制编码问题,可以使用十六进制格式的python保存图像,然后使用UNHEX将其安全地解码回原始二进制格式。
UPDATE t SET blob_col=UNHEX(LOAD_FILE('/tmp/image.png.hex')) WHERE id=1;
如果您的网络服务器位于同一台服务器上,这两个选项都需要您将文件保存在MySQL服务器文件系统上,否则您可能必须使用类似scp或ftp之类的东西将文件传输到MySQL服务器SQL语句。