I'm trying to make a link to a file path on a Windows server downloadable to the user after they click the file link.
My app displays entries from a result of searching a ticket model. The results on the page include items like: Ticket number, description, status and a link to a flat file (that is stored on a Windows server network share drive; starting with \server.name\folder A\folder B\folder C\file to download.txt
Note
On the display page/template.html I can list all my values in a table (even a link the the file I'd like to download). However, when I hover over the link at the bottom of the browser I see file://server.name/folder A/folder B\\folder C\\file to download.txt
. Yes, the last "slash" is a forward slash while all the others are back slashes (not sure why they are changing?)
When I pass the file address to the template it is formatted like : \\server.name\\folder A\\folder B\\folder C\\file to download.txt
(I can see that in testing when I just displayed the filepath on the page.
How do you make the link to a file path on a Windows server downloadable to users that wish to download the file?
.html
<body>
<h1><p>Ticket Number: {{ thisincident.IncidentID }}</p></h1>
<h3>Description: {{ thisincident.Description }}</h3>
<h4><p>Full Description</h4> {{ thisincident.FullDescription | linebreaks }}</p>
Journal Entry #
Date
Person
Journal Entry
File Name
{% for f in je %}
{{ f.JE }}
{{ f.Date }}
{{ f.resource }}
{{ f.entry | linebreaks }}
<a href="{{ f.Location }}">Download</a>
{% endfor %}
view.py
def ticket_view(request, IncidentID):
file_contents = []
thisincident = ticket.objects.get(id=IncidentID)
for root, dirs, files in os.walk(thisincident.LocationPath):
for file in files:
if not file == 'manifest.json':
path_file = os.path.join(root, file)
path_file = path_file.replace(thisincident.LocationPath + "\\", "")
file_contents.append(path_file)
log_list = parseJElog(thisincident.logfiletoparse)
data = {
"thisincident": thisincident,
"result": file_contents,
"je":log_list
}
return render(request, "ticket.html", data)
urls.py
urlpatterns = [
url(r'^homepage/$', views.home, name='home'),
url(r'^tickets/$', views.tickets, name='tickets'),
url(r'^ticket/(?P<IncidentID>\d+)$', views.ticket_view, name='ticket'),
]
if settings.DEBUG:
urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
MEDIA_BASE_ROOT = "\\server.name\\folder A\\folder B"
MEDIA_ROOT = os.path.join(MEDIA_BASE_ROOT, "\\folder B\\")
MEDIA_URL = ''
I'm fairly new to Django so any help will be much appreciated.
I also had a similar issue before. You can follow these steps to solve this. I will split the logic into two functions to make this straightforward and easy.
1, display the tickets
def ticket_view(request, IncidentID):
thisincident = ticket.objects.get(id=IncidentID)
log_list = parseJElog(thisincident.logfiletoparse)
data = {
"thisincident": thisincident,
"je": log_list
}
return render(request, "ticket.html", data)
2, download the file
import os
from django.http import FileResponse
def download_file(request, file_path):
file_name = os.path.basename(file_path)
file = open(file_path, 'rb')
response = FileResponse(file)
response['Content-Disposition'] = f'attachment; filename="{file_name}"'
return response
I think this is the code you need, the issue your face can be simply solved by using the os.path
or you can use pathlib
. here we are passing the file path
as an argument into the function and it opens the file in binary mode, creates a FileResponse with the file content, and sets the Content-Disposition
header to specify the filename for the user to download it.
Content-Disposition
header is an optional header by the way.
more about Content-Disposition
3, update your URLs according to the functions we define above.
4, update your template.
{% for f in je %}
{{ f.JE }}
{{ f.Date }}
{{ f.resource }}
{{ f.entry | linebreaks }}
<a href="{% url 'download_file' file_path=f.Location %}">Download</a>
{% endfor %}
5, update your settings
MEDIA_URL = '/media/' # edit this to your requirements
MEDIA_ROOT = '\\server.name\folder A\folder B\folder C' # Windows server path
# make sure that you also serving media files in the URL
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I hope this solution helps you.