我怎麼能限制FileField
僅在一個優雅的方式,服務器端接受某種類型的文件(視頻,音頻,PDF等)的?只接受的FileField某個文件類型,服務器端
回答
一個非常簡單的方法是使用自定義驗證器。
在您的應用程序的validators.py
:
def validate_file_extension(value):
import os
from django.core.exceptions import ValidationError
ext = os.path.splitext(value.name)[1] # [0] returns path+filename
valid_extensions = ['.pdf', '.doc', '.docx', '.jpg', '.png', '.xlsx', '.xls']
if not ext.lower() in valid_extensions:
raise ValidationError(u'Unsupported file extension.')
然後在您的models.py
:
from .validators import validate_file_extension
...和使用驗證你的表單字段:
class Document(models.Model):
file = models.FileField(upload_to="documents/%Y/%m/%d", validators=[validate_file_extension])
參見: How to limit file types on file uploads for ModelForms with FileFields?。
這應該被接受爲答案。非常感謝! – vabada 2016-06-28 10:33:23
@dabad只使用擴展名對文件驗證不好,這類答案會造成安全漏洞;請看到這些答案的人也檢查與不同格式和驗證器相關的CVE,以pillow/PIL爲例:O – 2016-08-24 06:10:50
有一個Django snippet做這個:
import os
from django import forms
class ExtFileField(forms.FileField):
"""
Same as forms.FileField, but you can specify a file extension whitelist.
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>>
>>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
>>>
>>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
>>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
>>>
>>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
Traceback (most recent call last):
...
ValidationError: [u'Not allowed filetype!']
"""
def __init__(self, *args, **kwargs):
ext_whitelist = kwargs.pop("ext_whitelist")
self.ext_whitelist = [i.lower() for i in ext_whitelist]
super(ExtFileField, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super(ExtFileField, self).clean(*args, **kwargs)
filename = data.name
ext = os.path.splitext(filename)[1]
ext = ext.lower()
if ext not in self.ext_whitelist:
raise forms.ValidationError("Not allowed filetype!")
#-------------------------------------------------------------------------
if __name__ == "__main__":
import doctest, datetime
doctest.testmod()
第一。在應用程序中創建一個名爲formatChecker.py的文件,其中您擁有要接受某種文件類型的FileField的模型。
這是您的formatChecker.py:
from django.db.models import FileField
from django.forms import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
class ContentTypeRestrictedFileField(FileField):
"""
Same as FileField, but you can specify:
* content_types - list containing allowed content_types. Example: ['application/pdf', 'image/jpeg']
* max_upload_size - a number indicating the maximum file size allowed for upload.
2.5MB - 2621440
5MB - 5242880
10MB - 10485760
20MB - 20971520
50MB - 5242880
100MB 104857600
250MB - 214958080
500MB - 429916160
"""
def __init__(self, *args, **kwargs):
self.content_types = kwargs.pop("content_types")
self.max_upload_size = kwargs.pop("max_upload_size")
super(ContentTypeRestrictedFileField, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs)
file = data.file
try:
content_type = file.content_type
if content_type in self.content_types:
if file._size > self.max_upload_size:
raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(self.max_upload_size), filesizeformat(file._size)))
else:
raise forms.ValidationError(_('Filetype not supported.'))
except AttributeError:
pass
return data
二。在你的models.py,補充一點:
from formatChecker import ContentTypeRestrictedFileField
然後,而不是使用 '的FileField',用這個 'ContentTypeRestrictedFileField'。
例子:
class Stuff(models.Model):
title = models.CharField(max_length=245)
handout = ContentTypeRestrictedFileField(upload_to='uploads/', content_types=['video/x-msvideo', 'application/pdf', 'video/mp4', 'audio/mpeg', ],max_upload_size=5242880,blank=True, null=True)
這些都是你擁有的東西,當你想只接受的FileField某些文件類型。
我認爲你最適合使用Dominic Rodger在他的回答中指定的ExtFileField和python-magic Daniel Quinn提到的最好的方法。如果某個人足夠聰明,至少可以改變擴展名,那麼你可以用標題來捕捉它們。
既然你已經確定這是最好的方法,爲什麼不張貼一些代碼來向我們展示呢? – Thismatters 2017-12-11 15:50:04
此外,我會擴大這個類與一些額外的行爲。
class ContentTypeRestrictedFileField(forms.FileField):
...
widget = None
...
def __init__(self, *args, **kwargs):
...
self.widget = forms.ClearableFileInput(attrs={'accept':kwargs.pop('accept', None)})
super(ContentTypeRestrictedFileField, self).__init__(*args, **kwargs)
當我們創建實例與PARAM接受=「PDF,.TXT」,在彈出的與文件結構作爲默認,我們將看到通過擴展名的文件。
您可以在設置中定義接受的MIME類型的列表,然後確定其使用Python魔法來檢測MIME類型,並提出ValidationError如果MIME類型是不被接受的驗證。在文件表單字段上設置驗證器。
唯一的問題是,有時的mime類型是application /八位字節流,這可能對應於不同的文件格式。你們有人解決了這個問題嗎?
版本1.11
中的Django爲模型字段新增了FileExtensionValidator
,文檔位於:https://docs.djangoproject.com/en/dev/ref/validators/#fileextensionvalidator。
如何驗證文件擴展名的例子:
from django.core.validators import FileExtensionValidator
from django.db import models
class MyModel(models.Model):
pdf_file= models.FileField(upload_to='foo/', validators=[FileExtensionValidator(allowed_extensions=['pdf'])])
注意,此方法是並不安全。引用自Django文檔:
不要依賴文件擴展名的確認來確定文件的 類型。無論文件包含哪些數據 ,文件都可以重命名爲具有任何擴展名。
還有新的validate_image_file_extension
(https://docs.djangoproject.com/en/dev/ref/validators/#validate-image-file-extension)用於驗證圖像擴展名(使用Pillow)。
您可以使用下面的表單中的
file = forms.FileField(widget=forms.FileInput(attrs={'accept':'application/pdf'}))
有幾個人使用python-magic,以驗證該文件實際上是你期望接收的類型建議限制文件類型。這可以併入到在接受的答案建議validator
:
import os
import magic
from django.core.exceptions import ValidationError
def validate_is_pdf(file):
valid_mime_types = ['application/pdf']
file_mime_type = magic.from_buffer(file.read(1024), mime=True)
if file_mime_type not in valid_mime_types:
raise ValidationError('Unsupported file type.')
valid_file_extensions = ['.pdf']
ext = os.path.splitext(file.name)[1]
if ext.lower() not in valid_file_extensions:
raise ValidationError('Unacceptable file extension.')
該示例僅驗證一個pdf,但任何數量的MIME類型和文件擴展名的可被添加到陣列。
假設你保存在上面validators.py
你可以加入到這個模型中,像這樣:
from myapp.validators import validate_is_pdf
class PdfFile(models.Model):
file = models.FileField(upload_to='pdfs/', validators=(validate_is_pdf,))
- 1. Selenium服務器 - 只接受1個IP
- 2. 如何使用FileField瀏覽django中的服務器端文件?
- 3. 接受大文件的小型服務器組件
- 4. PHP服務器只接受某些圖像,跨域
- 5. 服務器不接受大文件
- 6. 服務器接受許多客戶端
- 7. 如何測試一個函數只接受某種類型?
- 8. 在服務器上接受客戶端的多個連接
- 9. Java服務器將只接受來自我的客戶端的一個條目
- 10. 如何讓wcf服務每次只接受1個客戶端
- 11. 讓套接字服務器接受多個客戶端
- 12. 接受多個客戶端的服務器 - 不工作
- 13. 訪問asp.net中服務器端的輸入類型文件
- 14. 什麼是服務器端文件的正確類型
- 15. 如何知道服務器是否接受特定類型的內容類型?
- 16. 服務器端formdata的數據類型
- 17. 只能上傳可接受的文件類型php
- 18. 如何只接受我的服務器中從某些特定服務器重定向的請求
- 19. NSUserScriptTask:接受的文件類型?
- 20. 接受客戶端的Java服務器套接字
- 21. nginx將文件類型傳遞到後端服務器
- 22. MySQL不接受某些數據類型
- 23. SVN只複製某些文件類型
- 24. Java;試圖製作一個接受多個客戶端連接的服務器
- 25. Linux的TCP服務器:接受連接
- 26. 如何讓HTML的「文件」類型的輸入元素只接受pdf文件?
- 27. 迫使我的財產只接受某些種類的數據類型
- 28. 保護rails後端服務器免受直接連接
- 29. 當服務器接受TCP連接時端口是否改變?
- 30. 接受客戶端請求與服務器套接字
爲了讓打開的對話框來限制文件對某些類型的客戶端,[見這個問題(HTTP: //stackoverflow.com/a/40847649/247696)。 – Flimm 2016-11-28 15:24:40