django上傳文件

template html(模板文件):
<form enctype="multipart/form-data" method="POST" action="/address/upload/">
<input type="file" name="file" /><br/>
<input type="submit" value="上傳文件" />

有如下一個form:
from django import forms
class UploadFileForm(forms.Form):
  title = forms.CharField(max_length=50)
  file = forms.FileField()
處 理這個form的視圖收到了在request.FILES中的文件數據。從上述form來的數據可能通過request.FILES['file']來存 取。特別注意的是,只有當request方法是POST,且發送request的<form>有屬性 enctype="multipart/form-data"時,request.FILES中包含文件數據,否則request.FILES爲空。
以下視圖函數:
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from somewhere import handle_uploader_file
def upload_file(request):
  if request.method == 'POST':
     form = UploadFileForm(request.POST, request.FILES)
     if form.is_valid():
        handle_uploaded_file(request.FILES['file'])
        return HttpResponseRedirect('/success/url')
  else:
     form = UploadFileForm()
  return render_to_response('upload.html', {'form': form})
必須要將request.FILES傳給form的構造函數,才能將文件數據綁定到form.
處理上傳文件
字典request.FILES中的每一個條目都是一個UploadFile對象。UploadFile對象有如下方法:
1、UploadFile.read():
  從文件中讀取全部上傳數據。當上傳文件過大時,可能會耗盡內存,慎用。
2、UploadFile.multiple_chunks():
  如上傳文件足夠大,要分成多個部分讀入時,返回True.默認情況,當上傳文件大於2.5M時,返回True。但這一個值可以配置。
3、UploadFile.chunks():
  返回一個上傳文件的分塊生成器。如multiple_chunks()返回True,必須在循環中使用chrunks()來代替read()。一般情況下直接使用chunks()就行。
4、UploadFile.name():上傳文件的文件名
5、UplaodFile.size():上傳文件的文件大小(字節)
由上面的說明可以寫出handle_uploaded_file函數
def handle_uploaded_file(f):
  destination = open('some/file/name.txt', 'wb+')
  for chunk in f.chunks():
    destination.write(chunk)
  destination.close()
上傳文件保存的位置
保存上傳文件前,數據需要存放在某個位置。默認時,當上傳文件小於2.5M時,django會將上傳文件的全部內容讀進內存。意味着保存文件只有一次從內存讀取,一次寫磁盤。
但當上傳文件很大時,django會把上傳文件寫到臨時文件中,然後存放到系統臨時文件夾中。
改變upload handler的行爲
三個設置控制django文件上傳的行爲:
FILE_UPLOAD_MAX_MEMORY_SIZE:直接讀入內存的最大上傳文件大小(字節數)。當大於此值時,文件存放到磁盤。默認2.5M字節
FILE_UPLOAD_TEMP_DIR
FILE_UPLOAD_PERMISSIONS:權限
FILE_UPLOAD_HANDLERS
上傳文件真正的處理器。修改此項設置可以完成自定義django上傳文件的過程。
默認是:
("django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler",)
先嚐試裝入內存,如不行就存入到臨時文件。



在我寫的教程中的第八講就有關於通訊錄的上傳處理,不過那時處理很簡單。

首先是 form 要寫正確,格式爲:

<form enctype="multipart/form-data" method="POST" action="/address/upload/">

文件上傳的input field的寫法爲:

<input type="file" name="file"/>

後臺的處理是使用 request.FILES。它是一個Dict值,你可以:

file_obj = request.FILES.get(‘file’, None)

這裏的’file’是與input field的名字一致的。如果file_obj不爲空,它將是一個字典,通過測試可以得知它都有什麼值。如果你參考 django 自帶的 request_response.txt 文檔,可以看到它主要有三個值:

  • content
    這是文件的內容
  • filename
    這是原文件名
  • content-type
    這是文件的mime類型

那麼它放在哪裏呢?應該是在內存中。因此接下來你可以對這個文件的內容進行處理了,是直接處理內容或保存到一個地方。

也許有人會問,那麼 settings.py 中的 MEDIA_ROOT 是做什麼用的。如果你不使用 django 的 Model 中的 FileField 或 ImageField 的話,它其實沒有什麼用。這個設置是用在 Model 的 FileField 中的。在創建一個 Model 時,如果你的 Model 中有與文件相關的字段,那麼 django 會根據每個文件字段生成一系列的方法,如:get_fieldname_filename() get_fieldname_url() save_fieldname_file()。fieldname是根據你在 Model 中所起的名字來的。而 save_fieldname_file 需要兩個參數,一個是文件名,另一個就是文件內容。因此,你可以使用這個方法來將上傳的文件保存。那麼保存到哪裏去了呢?就是 MEDIA_ROOT 這個目錄下。而 settings.py 中的 MEDIA_URL 就是用於 get_fieldname_url() 這個方法的。

因此,MEDIA_ROOT 只與 Model 有關。



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