django文件上傳和下載的介紹

原文地址:http://www.ahlinux.com/python/13668.html


分享下Django文件上傳機制的用法,包括基本上傳文件的原理,以及如何處理上傳文件的方法,需要的朋友參考下。

當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請求的

有屬性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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章