[英]Python bottle - How to upload media files without DOSing the server
I was using the answer from this question and saw the comment: 我正在使用此问题的答案,并看到了以下评论:
raw = data.file.read() # This is dangerous for big files
How do I upload the file without doing this? 如何不执行此操作就上传文件? My code so far is:
到目前为止,我的代码是:
@bottle.route('/uploadLO', method='POST')
def upload_lo():
upload_dir = get_upload_dir_path()
files = bottle.request.files
print files, type(files)
if(files is not None):
file = files.file
print file.filename, type(file)
target_path = get_next_file_name(os.path.join(upload_dir, file.filename))
print target_path
shutil.copy2(file.read(), target_path) #does not work. Tried it as a replacement for php's move_uploaded_file
return None
which gives this output: 给出以下输出:
127.0.0.1 - - [03/Apr/2014 09:29:37] "POST /uploadLO HTTP/1.1" 500 1418
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\bottle.py", line 862, in _handle
return route.call(**args)
File "C:\Python27\lib\site-packages\bottle.py", line 1727, in wrapper
rv = callback(*a, **ka)
File "C:\dev\project\src\mappings.py", line 83, in upload_lo
shutil.copy2(file.read(), target_path)
AttributeError: 'FileUpload' object has no attribute 'read'
I am using python bottle v.12, dropzone.min.js, and mongodb. 我正在使用python bottle v.12,dropzone.min.js和mongodb。 I also am using this tutorial:
我也在使用本教程:
http://www.startutorial.com/articles/view/how-to-build-a-file-upload-form-using-dropzonejs-and-php http://www.startutorial.com/articles/view/how-to-build-a-file-upload-form-using-dropzonejs-and-php
This is called "file slurping": 这称为“文件提取”:
raw = data.file.read()
and you don't want to do it (at least in this case). 并且您不想这样做 (至少在这种情况下)。
Here's a better way to read a binary file of unknown (possibly large) size: 这是读取大小未知(可能很大)的二进制文件的更好方法:
data_blocks = []
buf = data.file.read(8192)
while buf:
data_blocks.append(buf)
buf = data.file.read(8192)
data = ''.join(data_blocks)
You may also want to stop iterating if the accumulated size exceeds some threshold. 如果累积大小超过某个阈值,您可能还想停止迭代。
Hope that helps! 希望有帮助!
PART 2 第2部分
You asked about limiting the file size, so here's an amended version that does that: 您询问有关限制文件大小的问题,因此,这是一个修改后的版本,它可以实现以下目的:
MAX_SIZE = 10 * 1024 * 1024 # 10MB
BUF_SIZE = 8192
# code assumes that MAX_SIZE >= BUF_SIZE
data_blocks = []
byte_count = 0
buf = f.read(BUF_SIZE)
while buf:
byte_count += len(buf)
if byte_count > MAX_SIZE:
# if you want to just truncate at (approximately) MAX_SIZE bytes:
break
# or, if you want to abort the call
raise bottle.HTTPError(413, 'Request entity too large (max: {} bytes)'.format(MAX_SIZE))
data_blocks.append(buf)
buf = f.read(BUF_SIZE)
data = ''.join(data_blocks)
It's not perfect, but it's simple and IMO good enough. 它并不完美,但是很简单,而且IMO足够好。
To add to ron.rothman's excellent answer...to fix your error message try this 要添加到ron.rothman的出色答案中...要修复您的错误消息,请尝试以下操作
@bottle.route('/uploadLO', method='POST')
def upload_lo():
upload_dir = get_upload_dir_path()
files = bottle.request.files
# add this line
data = request.files.data
print files, type(files)
if(files is not None):
file = files.file
print file.filename, type(file)
target_path = get_next_file_name(os.path.join(upload_dir, file.filename))
print target_path
# add Ron.Rothman's code
data_blocks = []
buf = data.file.read(8192)
while buf:
data_blocks.append(buf)
buf = data.file.read(8192)
my_file_data = ''.join(data_blocks)
# do something with the file data, like write it to target
file(target_path,'wb').write(my_file_data)
return None
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.