I have a function view that creates a file based on two parameters, and returns it with FileResponse. When called from a template url, this works fine. BUT…calls creating/returning large files can take a while – several seconds or more. So I need to start and stop a spinner in the GUI. My understanding is there are no accessible events involving the File/Save window - at least none on save or close of the window.
So I’ve tried executing the view with an ajax call, and that does start the spinner, generate the file, and stops the spinner, BUT…no file/save window opens! Below are the relevant code snippets. Seems like a routine thing to do, but haven’t worked out a solution after trying many things.
The two fallback options I can think of are 1) no spinner; 2) generate the file and a link to it somwhere. But is this actually doable? and is there a better alternative?
template
<a href="{% url 'download' id=ds.id format='json' %}" ref="lpf">download json</a>
<a href="{% url 'download' id=ds.id format='tsv' %}" ref="lpf">download tsv</a>
ajax GET
$("#downloads a").click(function(e){
urly='/datasets/{{ds.id}}/augmented/'+$(this).attr('ref')
startDownloadSpinner()
$.ajax({
type: 'GET',
url: urly
}).done(function() {
spinner_dl.stop();
console.timeEnd('big dl')
})
})
ajax POST alternative
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
$.ajax({
type: 'POST',
url: urly,
headers: {'X-CSRFToken': csrftoken},
mode: 'same-origin'
}).done(function() {
spinner_dl.stop();
})
view
def download(request, *args, **kwargs):
from django.db import connection
user = request.user.username
ds=get_object_or_404(Dataset,pk=kwargs['id'])
date=maketime()
req_format = kwargs['format']
if req_format is not None:
print('download format',req_format)
features=ds.places.all().order_by('id')
if req_format == 'tsv':
# make file name
fn = 'media/user_'+user+'/'+ds.label+'_aug_'+date+'.tsv'
with open(fn, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile, delimiter='\t', quotechar='', quoting=csv.QUOTE_NONE)
writer.writerow(['id','whg_pid','title','ccodes','lon','lat','added','matches'])
for f in features:
geoms = f.geoms.all()
gobj = augGeom(geoms)
row = [str(f.src_id),
str(f.id),
f.title,
';'.join(f.ccodes),
gobj['lonlat'][0] if 'lonlat' in gobj else None,
gobj['lonlat'][1] if 'lonlat' in gobj else None,
gobj['new'] if 'new' in gobj else None,
str(augLinks(f.links.all()))
]
writer.writerow(row)
response = FileResponse(open(fn, 'rb'), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="'+os.path.basename(fn)+'"'
return response
elif req_format == 'json':
... similar to above, but json
return response