简体   繁体   English

Django视图从服务器下载文件

[英]Django view to download a file from server

I have a views.py that:我有一个views.py:

  • creates some .xlsx files创建一些 .xlsx 文件
  • select the correct .zip and place the file inside选择正确的 .zip 并将文件放入其中

After that, I want this .zip to be automatically downloaded.之后,我希望自动下载这个 .zip。 I did some research and tested some codes but none worked.我做了一些研究并测试了一些代码,但没有一个有效。

I created a "temp" folder in the root of the app where the created files are stored.我在存储创建的文件的应用程序的根目录中创建了一个“临时”文件夹。

simplified view.py简化视图.py

def generate_ws(request,cource,ca_id):
    ca = get_object_or_404(CreditAnalysis,pk=ca_id)
    ca_owners = CAOwner.objects.filter(ca_operation=ca)
    mo_farms = MOFarm.objects.filter(ca_operation=ca)
    misses = []

    generate_owner_mo(ca_owner,misses,city)
    zip_name = 'temp/MOs - ' + str(ca_owner.owner) + '.zip'
    zf = zipfile.ZipFile(zip_name,'w')
    zf.close()

    generate_farm_mo(mo_farm,misses,city)
    generate_production_mo(ca,misses,city,production_city,pks)

    files = glob.glob('temp/*.xlsx')       #SELECT FILES AND PUT IN .ZIP
    for file in files:
        file_key = file.split('.')[0]
        file_key=file_key.split(' - ')
        for ca_owner in ca_owners:
            zip_name = 'temp/MOs - ' + str(ca_owner.owner) + '.zip'
            if str(ca_owner.owner) in file_key:
                zf = zipfile.ZipFile(zip_name,'a')
                new_file_name = file[5:]
                zf.write(file,new_file_name)
                zf.close()                
                break
     files = glob.glob('temp/*.zip')             # GET .ZIP FILES
     for file in files:
         download_mo(request,file)               # CREATE A DOWNLOAD FOR EACH .ZIP FILE

    misses = list(set(misses))

    return render(request,'generate_mo.html',{'misses':misses,})

download_mo下载_mo

def download_mo(request,file):
    path_to_file = os.path.realpath(file)
    with open(path_to_file,'rb') as fh:
        response = HttpResponse(fh.read())
        file_name = file[5:]                       #WITHDRAW "temp/"
        response['Content-Disposition'] = 'inline; filename=' + file_name
        return response

Everything works correctly except the download which never starts一切正常,除了永远不会开始的下载

In order to download a file, you need to return a FileResponse to the user.为了下载文件,您需要向用户返回一个FileResponse However, calling an external function that returns a FileResponse won't work because you're not actually returning the FileResponse to the user, in your case the user only receives the render(request, 'generate_mo.html', {'misses':misses,}) so that won't download the files.但是,调用返回FileResponse的外部函数将不起作用,因为您实际上并未将FileResponse返回给用户,在您的情况下,用户只收到render(request, 'generate_mo.html', {'misses':misses,})这样就不会下载文件。

You can't download several files one after the others, so I suggest putting them all in a .zip or .tar file so that you can download them as only one file, and only need to return one FileResponse .您不能一个接一个地下载多个文件,因此我建议将它们全部放在一个 .zip 或 .tar 文件中,这样您就可以将它们作为一个文件下载,并且只需要返回一个FileResponse

As you also need to render your template, what you can do is redirect to your download_mo view on template loading so that your file is downloaded while your template is rendered.由于您还需要渲染模板,您可以做的是在模板加载时重定向到您的download_mo视图,以便在渲染模板时下载文件。

Now, for your download_mo view, just replace your HttpResponse with a FileResponse :现在,对于您的download_mo视图,只需将您的HttpResponse替换为FileResponse

from django.http import FileResponse
def download_mo(request,file):
    path_to_file = os.path.realpath(file)
    response = FileResponse(open(path_to_file, 'rb'))
    file_name = file[5:]
    response['Content-Disposition'] = 'inline; filename=' + file_name
    return response

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM