【问题标题】:Django download file not workingDjango下载文件不起作用
【发布时间】:2011-03-13 21:16:54
【问题描述】:

我正在尝试在用户的机器上制作一个用于下载上传文件的脚本。问题是下载根本不起作用(它要么给我下载一个空文件,要么给我一些错误)。

最后一个错误是: 强制转换为 Unicode:需要字符串或缓冲区,找到 FieldFile

def download_course(request, id):
    course = Courses.objects.get(pk = id).course

    path_to_file = 'root/cFolder'
    filename = course # Select your file here.                                
    wrapper = FileWrapper(file(course))
    content_type = mimetypes.guess_type(filename)[0]
    response = HttpResponse(wrapper, content_type = content_type)
    response['Content-Length'] = os.path.getsize(filename)
    response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(course)

    return response

如何正确声明文件名,以便每次都知道要下载的文件: 文件名实际上是上面声明的“课程”

谢谢!

【问题讨论】:

    标签: django file forms download


    【解决方案1】:

    已编辑

    我认为您需要从 FileField 对象中提取 path 值:

    def download_course(request, id):
        course = Courses.objects.get(pk = id).course
    
        path = course.path # Get file path
        wrapper = FileWrapper( open( path, "r" ) )
        content_type = mimetypes.guess_type( path )[0]
    
        response = HttpResponse(wrapper, content_type = content_type)
        response['Content-Length'] = os.path.getsize( path ) # not FileField instance
        response['Content-Disposition'] = 'attachment; filename=%s/' % \ 
                                           smart_str( os.path.basename( path ) ) # same here
    
        return response
    

    为什么会这样:

    假设我有(嗯,我实际上有)模型:

    class DanePracodawcy( DaneAdresowe, DaneKontaktowe ):
        # other fields
        logo = ImageWithThumbnailsField( upload_to = 'upload/logos/',
                                      thumbnail = {'size': (180, 90)},
                                      blank = True )
    

    ImageWithThumbnailsField 是 FileField 的子类,所以它的行为方式相同。现在,当我执行 SELECT 时:

    mysql> select logo from accounts_danepracodawcy;
    +-----------------------------+
    | logo                        |
    +-----------------------------+
    | upload/logos/Lighthouse.jpg |
    +-----------------------------+
    1 row in set (0.00 sec)
    

    它显示(相对于 MEDIA_ROOT)存储文件的路径。但是当我访问logo Model 属性时:

    [D:projekty/pracus]|1> from accounts.models import DanePracodawcy
    [D:projekty/pracus]|4> DanePracodawcy.objects.get().logo
                       <4> <ImageWithThumbnailsFieldFile: upload/logos/Lighthouse.jpg>
    [D:projekty/pracus]|5> type( _ )
                       <5> <class 'sorl.thumbnail.fields.ImageWithThumbnailsFieldFile'>
    

    我得到了一些对象的实例。如果我尝试将该实例传递给os.path.getsize:

    [D:projekty/pracus]|8> import os.path
    [D:projekty/pracus]|9> os.path.getsize( DanePracodawcy.objects.get().logo )
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    
    D:\projekty\pracus\<ipython console> in <module>()
    
    C:\Python26\lib\genericpath.pyc in getsize(filename)
         47 def getsize(filename):
         48     """Return the size of a file, reported by os.stat()."""
    ---> 49     return os.stat(filename).st_size
         50
         51
    
    TypeError: coercing to Unicode: need string or buffer, ImageWithThumbnailsFieldFile found
    

    我得到 TypeError,就像你一样。所以我需要文件路径为字符串,可以通过path属性获取:

    [D:projekty/pracus]|13> os.path.getsize(  DanePracodawcy.objects.get().logo.path )
                       <13> 561276L
    

    或者,我可以通过 MEDIA_ROOT 设置获得name 属性和os.path.join

    [D:projekty/pracus]|11> from django.conf import settings
    [D:projekty/pracus]|12> os.path.getsize(  os.path.join( settings.MEDIA_ROOT, DanePracodawcy.objects.get().logo.name ) )
                       <12> 561276L
    

    但那是不必要的打字。

    最后要注意的是:因为path 是绝对路径,所以我需要提取文件名以将其传递给 Content-Disposition 标头:

    [D:projekty/pracus]|16> DanePracodawcy.objects.get().logo.path
                       <16> u'd:\\projekty\\pracus\\site_media\\upload\\logos\\lighthouse.jpg'
    [D:projekty/pracus]|17> os.path.basename( DanePracodawcy.objects.get().logo.path )
                       <17> u'lighthouse.jpg'
    

    【讨论】:

    • nop,课程名称是表中'course'字段对应
    • hmm .. 这太奇怪了,因为我的错误仍然强制转换为 Unicode: need string or buffer, FieldFile found 。我真的不明白为什么。
    • 对不起,我的回答错了,我再次检查并编辑。现在上面的代码应该可以按预期工作,我试图解释为什么它会这样工作。
    • 完美运行!!只是你忘了在那里声明 filename = course.name 。我已经接受了答案。您是否也可以在此处发布您的答案的链接:stackoverflow.com/questions/3141682/django-download-file-empty(我已经获得了赏金,我也想在那里接受您的答案。谢谢!)
    • 我上次编辑了一个,以更正未声明的文件名(我将该变量命名为path,因为我认为在这段代码中这种方式更合适)。很高兴我能帮忙:)
    【解决方案2】:

    除非您让用户下载动态生成的文件,否则我不明白您为什么需要这样做。

    您可以让这个视图重定向到适当的路径,并且相应的标题由为静态文件提供服务的服务器设置;通常是 apache 或 nginx

    我会按如下方式执行您的此视图:

    from django.conf import settings
    
    def download_course(request,id):
        course = get_object_or_404(Course,id=id)
        filename = course.course
        return redirect('%s/%s'%(settings.MEDIA_URL,filename))
    

    享受:)

    【讨论】:

    • 现在它说:“FieldFile”对象没有属性“_default_manager”
    猜你喜欢
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 2017-11-17
    • 2012-11-26
    • 2020-12-28
    • 1970-01-01
    相关资源
    最近更新 更多