서버 측 FileField에서 특정 파일 유형 만 허용
FileField
서버 측에서 특정 유형의 파일 (비디오, 오디오, pdf 등) 만 허용하도록 제한 하려면 어떻게 해야합니까?
매우 쉬운 방법 중 하나는 사용자 지정 유효성 검사기를 사용하는 것입니다.
앱에서 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])
참고 항목 : FileFields가있는 ModelForms의 파일 업로드에 대한 파일 유형을 제한하는 방법은 무엇입니까? .
버전의 Django에는 모델 필드 용 1.11
으로 새로 추가 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 사용).
이를 수행하는 Django 스 니펫 이 있습니다.
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()
먼저. 특정 파일 형식을 허용하려는 FileField가있는 모델이있는 앱 내부에 formatChecker.py라는 파일을 만듭니다.
이것은 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에서 특정 파일 유형 만 허용하려는 경우 이러한 작업이 필요합니다.
You can use the below to restrict filetypes in your Form
file = forms.FileField(widget=forms.FileInput(attrs={'accept':'application/pdf'}))
A few people have suggested using python-magic to validate that the file actually is of the type you are expecting to receive. This can be incorporated into the validator
suggested in the accepted answer:
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.')
This example only validates a pdf, but any number of mime-types and file extensions can be added to the arrays.
Assuming you saved the above in validators.py
you can incorporate this into your model like so:
from myapp.validators import validate_is_pdf
class PdfFile(models.Model):
file = models.FileField(upload_to='pdfs/', validators=(validate_is_pdf,))
I think you would be best suited using the ExtFileField that Dominic Rodger specified in his answer and python-magic that Daniel Quinn mentioned is the best way to go. If someone is smart enough to change the extension at least you will catch them with the headers.
Additionally i Will extend this class with some extra behaviour.
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)
When we create instance with param accept=".pdf,.txt", in popup with file structure as a default we will see files with passed extension.
You can define a list of accepted mime types in settings and then define a validator which uses python-magic to detect the mime-type and raises ValidationError if the mime-type is not accepted. Set that validator on the file form field.
The only problem is that sometimes the mime type is application/octet-stream, which could correspond to different file formats. Did someone of you overcome this issue?
ReferenceURL : https://stackoverflow.com/questions/3648421/only-accept-a-certain-file-type-in-filefield-server-side
'Development Tip' 카테고리의 다른 글
내 DateTime을 UTC로 변환하는 데 문제가 있습니다. (0) | 2021.01.05 |
---|---|
`File` 객체의 액세스 모드 (예 : w +, r +)의 차이점 (0) | 2021.01.05 |
PHP에서 문자열이 base64인지 확인하는 방법 (0) | 2021.01.05 |
부드러운 곡선 그리기-필요한 방법 (0) | 2021.01.05 |
AngularJS에서 필터링 된 결과 강조 (0) | 2021.01.05 |