如何在Django中获取文件的扩展名?

10

我将在Django中构建一个Web应用程序。 我有一个表单,可以将文件发送到views.py。

视图:

@login_required(login_url=login_url)
def addCancion(request):
    if request.method == 'POST':
        form2 = UploadSong(request.POST, request.FILES)
        if form2.is_valid():
            if(handle_uploaded_song(request.FILES['file'])):
                path = '%s' % (request.FILES['file'])
                ruta =  "http://domain.com/static/canciones/%s" % path
                usuario = Usuario.objects.get(pk=request.session['persona'])
                song = Cancion(autor=usuario, cancion=ruta)
                song.save()
                return HttpResponse(ruta)
            else:
                return HttpResponse("-3")
        else:
            return HttpResponse("-2")
    else:
        return HttpResponse("-1")   

我想上传只有MP3文件,但是不知道如何过滤。

我尝试了一个名为“ContentTypeRestrictedFileField(FileField):”的类,但没有成功。

我该如何在views.py中获取文件类型?

谢谢!


你的 'content_type' 变量是从哪里来的?只是好奇。 - forivall
抱歉,这是一个错误。谢谢。 - Marcos Aguayo
7个回答

16

您也可以使用表单中的clean()方法,该方法用于验证表单。因此,您可以拒绝不是mp3格式的文件。代码示例如下:

class UploadSong(forms.Form):
    [...]

    def clean(self):
        cleaned_data = super(UploadSong, self).clean()
        file = cleaned_data.get('file')

        if file:
            filename = file.name
            print filename
            if filename.endswith('.mp3'):
                print 'File is a mp3'
            else:
                print 'File is NOT a mp3'
                raise forms.ValidationError("File is not a mp3. Please upload only mp3 files")

        return file

你从哪里得到了docfile.name中的docfile? - user875139
嗯,这是个错误,应该是文件,在上一行刚检查过。可能是复制粘贴的错误,抱歉 :) - dleal
这个答案被标记为正确有点奇怪 - 它只检查文件名,下面使用魔数检查的答案是更好和更安全的方式。 - Evgeny Malkov
如果用户上传的文件以mp3结尾,这是不安全的,应该予以阻止。 - undefined

6

获取请求的直接地址:

import os


extesion = os.path.splitext(str(request.FILES['file_field']))[1]

或者在数据库模型中获取扩展。
import os

file = FileModel.objects.get(pk=1)  # select your object
file_path = file.db_column.path  # db_column how you save name of file.

extension = os.path.splitext(file_path)[1]

6

5
你是指这个吗:
u_file = request.FILES['file']            
extension = u_file.split(".")[1].lower()

if(handle_uploaded_song(file)):
    path = '%s' % u_file
    ruta =  "http://example.com/static/canciones/%s" % path
    usuario = Usuario.objects.get(pk=request.session['persona'])
    song = Cancion(autor=usuario, cancion=ruta)
    song.save()
    return HttpResponse(content_type)

1
或者 os.path.splitext(file)[1] - Aya
1
我遇到了这个错误:'InMemoryUploadedFile'对象没有'split'属性。 - Marcos Aguayo
如果他要做的只是基于文件扩展名进行过滤,那么这实际上只是方便功能(某人可以轻松上传包含任意数据的带有MP3文件扩展名的文件,或者没有该文件扩展名的MP3文件),因此他应该在客户端执行以减少请求大小。 - Silas Ray
我希望在 Django 中的扩展能够在服务器端进行过滤,而不是在客户端进行过滤。 - Marcos Aguayo
@MarcosAguayo,在 handle_uploaded_song 中存在冲突,请尝试将其放在 handle_uploaded_song 之前。 - catherine
显示剩余3条评论

2
您可以使用request.FILES["file_field_name"].content_type
my_file = request.FILES["file_field_name"]
if my_file.content_type != 'text/csv':
    print("Your file must be a CSV type")


1

使用 FileType.py 库。

示例

kind = filetype.guess('tests/fixtures/sample.jpg')
if kind is None:
    print('Cannot guess file type!')
    return

print('File extension: %s' % kind.extension)
print('File MIME type: %s' % kind.mime)

@Marceio Soares 这个无法从 request.data 中猜测出 PDF 扩展名。 - Pran Kumar Sarkar
@PranKumarSarkar 你确定你使用的PDF文件是正常工作的吗?你使用的是哪个版本的Python? 我刚刚尝试使用了电脑上的Python版本3.6.9和一个PDF文件,结果运行良好。 - Marcelo Soares
Python 3.7 我没有从存储中猜测 PDF 文件扩展名。我试图从内存文件 request.data.get('filenamefield') 在 Django 后端中检查它。 - Pran Kumar Sarkar

0

使用MimeTypes().guess_extension()方法。请查看下面的代码片段。

# guess the file extension
file_obj.seek(0)
mime = magic.from_buffer(file_obj.read(), mime=True)
extension = mimetypes.MimeTypes().guess_extension(mime)
>>> print extension
.jpeg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接