Ajax file download sets filename to random string of characters

I am trying to download a file using ajax. The download works correctly, however, the downloaded filename is set to a random string of characters. I don't think this is relevant since the backend is working, but I'm using django

js/html:

<script>
    function downloadFile(){
        var filename = 'data.txt';
        $.ajax({
            url: 'downloadFile',
            data: {'filename': filename},
            success: function(blob, status, xhr){
                var disposition = xhr.getResponseHeader('Content-Disposition');
                if (disposition && disposition.indexOf('attachment') != -1){
                    var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                    var matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1]){
                        filename = matches[1].replace(/['"]/g,'');
                    }
                }
                var bd = [];
                bd.push(blob);
                var typename = "application/" + filename;
                var downloadURL = window.URL.createObjectURL(new Blob(bd, {type: typename}));
                var a = document.createElement("a");
                a.href = downloadURL;
                document.body.append(a);
                a.click();
            }
        });
    }
</script>

...


<button id="downloadFile" type="button" onclick="downloadFile()"><i class="fa fa-download"></i></button>

...

django views.py:

import pathlib
import os

def downloadFile(request):
    fname = request.GET.get('filename')
    fpath = os.path.join(<local_filesystem_path>, fname)
    # code to generate file here
    if pathlib.Path(fpath).exists():
        file_download = open(fpath, 'rb')
        response = HttpResponse(file_download, content_type='application/{}'.format(fname))
        response['Content-Disposition'] = 'attachment; filename="{}"'.format(fname)
    return response

and urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('downloadFile', views.downloadFile, name='downloadFile')
]

When I click the download button, everything works correctly except that my file has been renamed to a random string of 8 characters. Each time I re-download it, the string changes, but it's always 8 characters long. I'm guessing that something is happening where my browser thinks that the filename is unset so it's assigning a random string. But I'd like to set it to something I've specified - how can I do this?

Try adding a download attribute to the the <a> tag that you create. It allows you to set the file name.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download

Back to Top