Signor
Signor

Reputation: 563

User-specific download file in django

i have an app in django that do some processes and build a file, in one section, i want to show the user that file to download that.
(for example, user enter a name in front-end and the app give him a pdf file to download).
the file building process is ok and it is in /app_dir/media/app/report/username/file.pdf here is my code, but it does not worked and i faced some problems. can you please help me, where is my problem? and how i can make that user-specefic? each user just can access to his files.


views.py (my_main_function):

@login_required(login_url='/login/')
def my_function(request):
    if request.method == 'GET':
        return render(request, 'app/my_function.html')

    else:
        try:
            #my main process to build .PDF file


        except ValueError:
            return render(request, 'app/dashboard.html', {'error':'Bad data passed in. Try again.'})

    return render(request, 'app/download.html')

views.py (download function):

def download_file(request):
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    filename = f"{file}.pdf"
    # Define the full file path
    filepath = f"{BASE_DIR}/app/media/app/reports/{user_name}/{filename}"
    # Open the file for reading content
    path =  open(filepath, 'rb')
    path.read()

    # Set the return value of the HttpResponse
    response = HttpResponse(path, content_type='application/pdf')
    # Set the HTTP header for sending to browser
    response['Content-Disposition'] = "attachment; filename=%s" % filepath
    # Return the response value
    return response

urls.py:

path('download/', views.download_file, name='download_file'),

simple testing download.html file:

<html>
    <title>Download File</title>
</head>
<body>
<enter>
   <h1>Download File using link</h1>
   <a href="{% url 'download_file' %}">Download PDF</a>
</center>
</body>
</html>

Upvotes: 0

Views: 836

Answers (1)

Alexey Popov
Alexey Popov

Reputation: 756

It is not clear what problems you have encountered, but there are some lines I would correct in your code

# first of all why not use django.http.FileResponse instead of HttpResponse?
# https://docs.djangoproject.com/en/3.2/ref/request-response/#fileresponse-objects
from django.http import FileResponse


# if you want files to be accessible only to owners 
# you probably should force user to login before download
@login_required
def download_file(request):
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    filename = f"{file}.pdf"
    filepath = f"{BASE_DIR}/app/media/app/reports/{user_name}/{filename}"
    
    # somewhere here you need to check if user has access to the file
    # if files ownership based solely on {user_name} dir in filesystem
    # then it is enough to check if file exists
    if os.path.exists(filepath):   
        response = FileResponse(open(filepath, 'rb'))

        # it is probably better to use filename instead of filepath
        response['Content-Disposition'] = "attachment; filename=%s" % filename

        return response
    else:
        raise Http404

Upvotes: 1

Related Questions