[Django]-Django download a file

138πŸ‘

βœ…

You missed underscore in argument document_root. But it’s bad idea to use serve in production. Use something like this instead:

import os
from django.conf import settings
from django.http import HttpResponse, Http404

def download(request, path):
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    if os.path.exists(file_path):
        with open(file_path, 'rb') as fh:
            response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
            response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
            return response
    raise Http404

66πŸ‘

You can add β€œdownload” attribute inside your tag to download files.

<a  href="/project/download" download> Download Document </a>

https://www.w3schools.com/tags/att_a_download.asp

πŸ‘€Hasan Basri

42πŸ‘

Reference:

In view.py Implement function like,

def download(request, id):
    obj = your_model_name.objects.get(id=id)
    filename = obj.model_attribute_name.path
    response = FileResponse(open(filename, 'rb'))
    return response
πŸ‘€mananbh9

8πŸ‘

When you upload a file using FileField, the file will have a URL that you can use to point to the file and use HTML download attribute to download that file you can simply do this.

models.py

The model.py looks like this

class CsvFile(models.Model):
    csv_file = models.FileField(upload_to='documents')

views.py

#csv upload

class CsvUploadView(generic.CreateView):

   model = CsvFile
   fields = ['csv_file']
   template_name = 'upload.html'

#csv download

class CsvDownloadView(generic.ListView):

    model = CsvFile
    fields = ['csv_file']
    template_name = 'download.html'

Then in your templates.

#Upload template

upload.html

<div class="container">
<form action="#" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.media }}
    {{ form.as_p }}
    <button class="btn btn-primary btn-sm" type="submit">Upload</button>
</form>

#download template

download.html

  {% for document in object_list %}

     <a href="{{ document.csv_file.url }}" download  class="btn btn-dark float-right">Download</a>

  {% endfor %}

I did not use forms, just rendered model but either way, FileField is there and it will work the same.

πŸ‘€sikaili99

4πŸ‘

I’ve found Django’s FileField to be really helpful for letting users upload and download files. The Django documentation has a section on managing files. You can store some information about the file in a table, along with a FileField that points to the file itself. Then you can list the available files by searching the table.

πŸ‘€Don Kirkby

3πŸ‘

  1. <a href='/your-download-view/' download>Download</a>

  2. In your view:

from django.http import FileResponse

def download(request):
    # pre-processing, authorizations, etc.
    # ...
    return FileResponse(open(path_to_file, 'rb'), as_attachment=True)
πŸ‘€Mourad Qqch

2πŸ‘

@Biswadp’s solution worked greatly for me

In your static folder, make sure to have the desired files you would like the user to download

In your HTML template, your code should look like this :

<a href="{% static 'Highlight.docx' %}"> Download </a>
πŸ‘€El Bachir

2πŸ‘

Using the below approach makes everything less secure since any user can access any user’s file.

<a  href="/project/download" download> Download Document </a>

Using the below approach makes no sense since Django only handles one requests at the time (unless you are using gunicorn or something else), and believe me, the below approach takes a lot of time to complete.

def download(request, path):
    file_path = os.path.join(settings.MEDIA_ROOT, path)
    if os.path.exists(file_path):
        with open(file_path, 'rb') as fh:
            response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
            response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
            return response
    raise Http404

So what is the optimum solution?
Use Nginx authenticated routes. When requesting a file from Nginx you can make a request to a route and depending on the HTTP response Nginx allows to denies that request. This makes it very secure and also scalable and performant.
You can ready about more here

2πŸ‘

import mimetypes
from django.http import HttpResponse, Http404

mime_type, _ = mimetypes.guess_type(json_file_path)
    
if os.path.exists(json_file_path):
    with open(json_file_path, 'r') as fh:
        response = HttpResponse(fh, content_type=mime_type)
        response['Content-Disposition'] = "attachment; filename=%s" % 'config.json'
        return response
raise Http404
πŸ‘€Gaurav Nagar

1πŸ‘

Simple using html like this downloads the file mentioned using static keyword

<a href="{% static 'bt.docx' %}" class="btn btn-secondary px-4 py-2 btn-sm">Download CV</a>
πŸ‘€Biswadp

1πŸ‘

1.settings.py:

MEDIA_DIR = os.path.join(BASE_DIR,'media')
#Media
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'

2.urls.py:

from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

3.in template:

<a href="{{ file.url }}" download>Download File.</a>

Work and test in django >=3

for more detail use this link:
https://youtu.be/MpDZ34mEJ5Y

1πŸ‘

If the file is a FileField in the model, this is the way I do it:

    try:
        download_file = PrintingFile.objects.get(pk=kwargs.get('pk_file', 0))
        return FileResponse(download_file.file.open(), as_attachment=True)
    except PrintingFile.DoesNotExist:
        raise Http404

More here

πŸ‘€cwhisperer

0πŸ‘

I use this method:

{% if quote.myfile %}
    <div class="">
        <a role="button" 
            href="{{ quote.myfile.url }}"
            download="{{ quote.myfile.url }}"
            class="btn btn-light text-dark ml-0">
            Download attachment
        </a>
    </div>
{% endif %}
πŸ‘€Shahriar.M

0πŸ‘

If you hafe upload your file in media than:

media
example-input-file.txt

views.py

def download_csv(request):    
    file_path = os.path.join(settings.MEDIA_ROOT, 'example-input-file.txt')    
    if os.path.exists(file_path):    
        with open(file_path, 'rb') as fh:    
            response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")    
            response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)    
            return response

urls.py

path('download_csv/', views.download_csv, name='download_csv'),

download.html

a href="{% url 'download_csv' %}" download=""
πŸ‘€Timeless

Leave a comment