Only accept a certain file type in FileField, server-side

前端 未结 10 594
日久生厌
日久生厌 2020-11-27 02:56

How can I restrict FileField to only accept a certain type of file (video, audio, pdf, etc.) in an elegant way, server-side?

相关标签:
10条回答
  • 2020-11-27 03:32

    You can use the below to restrict filetypes in your Form

    file = forms.FileField(widget=forms.FileInput(attrs={'accept':'application/pdf'}))
    
    0 讨论(0)
  • 2020-11-27 03:32

    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,))
    
    0 讨论(0)
  • 2020-11-27 03:34

    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.

    0 讨论(0)
  • 2020-11-27 03:36

    after I checked the accepted answer, I decided to share a tip based on Django documentation. There is already a validator for use to validate file extension. You don't need to rewrite your own custom function to validate whether your file extension is allowed or not.

    https://docs.djangoproject.com/en/3.0/ref/validators/#fileextensionvalidator

    Warning

    Don’t rely on validation of the file extension to determine a file’s type. Files can be renamed to have any extension no matter what data they contain.

    0 讨论(0)
提交回复
热议问题