2

My webpage has a functionality that lets users request fairly large json files (3MB+) to be generated. The generation process takes some time and I send them an email with a download link once it is ready.

My problem is that clicking the download URL will open the content of the json file in the browser instead of starting a download dialog.

I have found this question: Serving .json file to download but the solution reserialize the json file into the response:

mixed_query = list(invoices) + list(pcustomers)
json_str = serializers.serialize('json', mixed_query))
response = HttpResponse(json_str, content_type='application/json')
response['Content-Disposition'] = 'attachment; filename=export.json'

As the JSON file already exists, I do not want to rewrite it entirely within the response. I just want users to download the already generated file.

How can I force the URL to start a download when reached?

I am using Django 3.1, with Python 3.6

Here is the email template sent to users once the download link is ready:

{% extends "emails/email_css.html" %}

{% block mail_content %}
    <p>Hi, {{ username }}</p>

    <p>Your export for {{ export_name }} is ready!</p>
    <p>The file will be available for download for 2 days, or until you request a new export.</p>

    <a class="download_button" type="button" href={{ download_url }}>Download</a>
{% endblock %}

Edit: I also tried this solution How to download file using anchor tag <a> but the json file still gets shown in the browser instead of being downloaded.

Ryan Pergent
  • 4,432
  • 3
  • 36
  • 78

2 Answers2

0

I eventually found how to do it, by returning a FileResponse with as_attachment=True.

from django.http import FileResponse

def download_export(request):
    response = FileResponse(open("path/to/file.json", 'rb'), as_attachment=True,
                            filename="file_name.json")
    return response
Ryan Pergent
  • 4,432
  • 3
  • 36
  • 78
  • Does it work on mobile? I'm having a similar issue (with Rails, but the same headers). It works perfectly fine on desktop, but if I try it with my phone (iOS, Firefox) it will display the content of the JSON. – Gustavo G. Feb 17 '23 at 11:38
-1

Try adding the download property to the <a> tag. You can optionally specify a download filename or not.

Without filename:

<a class="download_button" type="button" href={{ download_url }} download>Download</a>

With filename:

<a class="download_button" type="button" href={{ download_url }} download="someJsonFile.json">Download</a>

See docs here for the download property. Also the related StackOverflow post here.

Dean Elliott
  • 1,245
  • 1
  • 8
  • 12
  • Unfortunately this still opens the json directly inside the browser instead of downloading it (both with and without the filename) – Ryan Pergent Jun 22 '21 at 11:37