Django文件上传机制用法详解
Django文件上传机制用法详解
http://www.jbxue.com/article/24283.html
当Django处理上传一个文件时,文件数据被放在request.FILES中。 这个文档解释文件怎么样被存储在磁盘上或者内存中,怎样定制默认的行为。
一,基本文件上传
考虑一个包含FileField的简单的表单:
复制代码 代码示例:
from django import forms
classUploadFileForm(forms.Form):
title=forms.CharField(max_length=50)
file=forms.FileField()
一个处理这个表单的视图将在request.FILES中接受文件数据 ,request.FILES是一个字典,它对每个FileField(或者是ImageField,或者是其他的FileField的子类)都包含一个key.所以 从上面的表单中来的数据将可以通过request.FILES[‘file‘]键来访问. 注意request.FILES只有 在request方法是POST并且发出POST请求的 <form> 有属性enctype="multipart/form-data".否则,request。FILES将是空的。
另一个简单的例子:
复制代码 代码示例:
from fdjango.http improt HttpResponseRedirect
from django.shortcuts import render_to_response
from somewhere import handle_uploaded_file
def upload_file(request):
if request.method == ‘post‘:
form = UploadFileForm(rquest.POST,request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES[‘file‘])
return HttpResponseRedirect(‘/success/ur/‘)
else:
form = UploadFileForm()
return render_to_response(‘upload.html‘,{‘form‘:form})
要注意,必须将request.FILES传递到表单的构造器中;这就是文件数据怎样和表单沾上边的 。
二,处理上传的文件
最后的难题是怎样处理从request.FILES中获得的真实的文件。
这个字典的每个输入都是一个UploadedFile对象——一个上传之后的文件的简单的包装。
通常会使用下面的几个方法来访问被上传的内容:
UploadedFile.read():从文件中读取整个上传的数据。小心整个方法:如果这个文件很大,你把它读到内存中会弄慢你的系统。你可以想要使用chunks()来代替,看下面;
UploadedFile.multiple_chunks():如果上传的文件足够大需要分块就返回真。默认的这个值是2.5兆,当然这个值是可以调节的,看下面的UploadedFile.chunks():一个产生器,返回文件的块。如果multiple_chunks()是真的话,你应该在一个循环中使用这个方法,而不是使用read();
UploadedFile.name:上传文件的名字(比如m_file.txt)
UploadedFile.size:以bytes表示的上传的文件的大小。
还有其他的几个方法和属性。你可以自己去查。
把他们放在一起,这里是一个你处理上传文件的通常方法:
复制代码 代码示例:
def handle_uploaded_file(f):
destination = open(‘some/file/name.txt‘,‘wb+‘)
for chunk in f.chunks():
destination.write(chunk)
destination.close()
在UploadedFile.chunks()上循环而不是用read()保证大文件不会大量使用你的系统内存。
三,上传的数据存在哪里?
在你保存上传的文件之前,数据需要被保存在某些地方。默认呢的,如果一个上传的文件小于2.5兆,Django会将上传的东西放在内存里。这意味着只要从内存读取数据并保存到硬盘上,所以很快。然而,如果一个上传的文件太大,Django将将上传的文件写到一个临时的文件中,这个文件在你的临时文件路径中。在Unix-like的平台上意味着你可以预见Django产生一个文件保存为/tmp/tmpzfp6I6.upload的文件。如果这个文件足够大,你可以观察到这个文件的大小在增大。
很多细节--2.5M;/tmp;等 等 都是简单的看上去合理的默认值。继续阅读看看你怎么样个性化或者完全替代掉上传行为。
四,改变上传处理行为
三个设置改变Django的上传处理行为:
FILE_UPLOAD_MAX_MEMORY_SIZE:以bytes为单位的到内存中的最大大小,。比这个值大的文件将被先存到磁盘上。默认是2.5兆
FILE_UPLOAD_TEMP_DIR:比FILE_UPLOAD_MAX_MEMORY_SIZE大的文件将被临时保存的地方。默认是系统标准的临时路径。
FILE_UPLOAD_PERMISSIONS:如果这个没有给出或者是None,你将获得独立于系统的行为。大多数平台,临时文件有一个0600模式,从内存保存的文件将使用系统标准umask。
FILE_UPLOAD_HANDLERS:上传文件的处理器。改变这个设置允许完全个性化——甚至代替——Django的上传过程。
默认是:
("django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler",)
UploadedFile 对象
class UploadedFile
作为那些重File继承的补充,素有的UploadedFile对象定义了下面的方法和属性:
UploadedFile.content_type
文件的content_type头(比如text/plain
orapplication/pdf
)。像用户提供的任何数据一样,你不应该信任上传的数据就是这个类型。你仍然要验证这个文件包含这个头声明的content-type——“信任但是验证”。
UploadedFile.charset
对于text/*的content-types,浏览器提供的字符集。再次,“信任但是验证”是最好的策略。
UploadedFile.temporary_file_path():只有被传到磁盘上的文件才有这个方法,它返回临时上传文件的全路径。
注意:
像通常的Python文件,你可以迭代上传的文件来一行一行得读取文件:
for line in uploadedfile: do_something_with(line)
然而,不同于标准Python文件,UploadedFile值懂得/n(也被称为Unix风格)的结尾。如果你知道你需要处理有不同风格结尾的文件的时候,你要在你的视图中作出处理。
五,上传处理句柄:
当一个用户上传一个文件,Django敬爱那个这个文件数据传递给上传处理句柄——一个处理随着文件上传处理文件的小类。上传处理句柄被FILE_UPLOAD_HANDLERS初始化定义,默认是:
复制代码 代码示例:
(
"django.core.files.uploadhandler.MemoryFileUploadHandler"
,
"django.core.files.uploadhandler.TemporaryFileUploadHandler"
,)
这两个提供了Django处理小文件和大文件的默认上产行为。 你可以个性化处理句柄来个性化Django处理文件的行为。比如你可以使用个性化的处理句柄来强制用户配额,实时地压缩数据,渲染进度条,甚至在保存在本地的同时向另一个存储地发送数据。
六,实时修改上传处理句柄
有的时候某些视图要使用不同的上传行为。这种情况下,你可以重写一个上传处理句柄,通过request.upload_handlers来修改。默认的,这个列表包含FILE_UPLOAD_HANDLERS提供的处理句柄,但是你可以像修改其他列表一样修改这个列表。
比如,加入你写了一个叫做
ProgressBarUploadHandler
的处理句柄。你可以通过下面的形式加到你的上传处理句柄中:
request.upload_handlers.insert(0,ProgressBarUploadHandler())
你赢使用list.insert()在这种情况下。因为进度条处理句柄需要首先执行。记住,处理句柄按照顺序执行。
如果你像完全代替掉上传处理句柄,你可以赋值一个新的列表:
request.upload_handlers=[ProgressBarUploadHandler()]
注意:你只能在访问request.POST或者request.FILES之前修改上传处理句柄。——如果上传处理开始后再改就没用了。如果你在修改reqeust.uplaod_handlers之前访问了request.POST
or request.FILES
,Django将抛出一个错误。
所以,在你的视图中尽早的修改上传处理句柄。
写自定义的上传处理句柄:
所有的上传处理句柄都应 是 django.core.files.uploadhandler.FileUploadHandler的子类。你可以在任何你需要的地方定义句柄。 需要的方法:
自定义的上传处理句柄必须定义一下的方法:FileUploadHandler.receive_data_chunk(self,raw_data,start):从文件上传中接收块。
raw_data是已经上传的字节流 start是raw_data块开始的位置
你返回的数据将被传递到下一个处理句柄的receive_data_chunk方法中。这样一个处理句柄就是另一个的过滤器了。
返回None将阻止后面的处理句柄获得这个块,当你 自己存储这个数据,而不想其他处理句柄存储拷贝时很有用。
如果你触发一个StopUpload或者SkipFile异常,上传将被放弃或者文件被完全跳过。 FileUploadHandler.file_complete(self, file_size)
当 文件上传完毕时调用。
处理句柄应该返回一个UploadFile对象,可以存储在request.FILES中。处理句柄也可以返回None来使得UploadFile对象应该来自后来的上传处理句柄。
剩下的就是可选的一些方法实现。
FILE_UPLOAD_MAX_MEMORY_SIZE = 209715200 FILE_UPLOAD_MAX_MEMORY_SIZE = 209715200
在你本机先好好测试一下,它是如何占用内存,什么时候开始存入temp目录,怎么迁移到upload目录底下的
文件上传的时候,如果一个上传的文件小于2.5兆,Django会将上传的东西放在内存里,如果上传的文件大于2.5M,Django将整个上传的文件写到一个临时的文件中,这个文件在临时文件路径中。上传完毕后,将调用View中的_Upload()方法将临时文件夹中的临时文件分块写到上传文件的存放路径下,每块的大小为64K,写完后临时文件将被删除。 UploadedFile.multiple_chunks():如果上传的文件足够大需要分块就返回真。默认的这个值是2.5兆,当然这个值是可以调节的,看下面的UploadedFile.chunks():一个产生器,返回文件的块。如果multiple_chunks()是真的话,你应该在一个循环中使用这个方法,而不是使用read();
在你保存上传的文件之前,数据需要被保存在某些地方。默认呢的,如果一个上传的文件小于2.5兆,Django会将上传的东西放在内存里。这意味着只要从内存读取数据并保存到硬盘上,所以很快。然而,如果一个上传的文件太大,Django将上传的文件写到一个临时的文件中,这个文件在你的临时文件路径中。在Unix-like的平台上意味着你可以预见Django产生一个文件保存为/tmp/tmpzfp6I6.upload的文件。如果这个文件足够大,你可以观察到这个文件的大小在增大。
三个设置改变Django的上传处理行为:
FILE_UPLOAD_MAX_MEMORY_SIZE:以bytes为单位的到内存中的最大大小,。比这个值大的文件将被先存到磁盘上。默认是2.5兆
FILE_UPLOAD_TEMP_DIR:比FILE_UPLOAD_MAX_MEMORY_SIZE大的文件将被临时保存的地方。默认是系统标准的临时路径。
FILE_UPLOAD_PERMISSIONS:如果这个没有给出或者是None,你将获得独立于系统的行为。
大多数平台,临时文件有一个0600模式,从内存保存的文件将使用系统标准umask。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。