【发布时间】:2019-09-12 20:19:37
【问题描述】:
我有一个 celery 任务,只需单击一个按钮即可创建 PDF 文件。
当按钮被点击时,javascript端会一直检查直到任务完成,当完成时,它会下载文件。我想一些递归会做:
$(".getPdf").on('click', function(event) {
// Grab the clicked object ID and the filename stored on the data attributes
var thisId = $(this).data('runid');
var filename = $(this).data('filename');
var taskID = "None";
var pdfStatus = "None";
// Run download function
downloadPdf(filename, taskID, pdfStatus);
function downloadPdf(filename, taskID, pdfStatus) {
// Send a POST request to Django's RunsView with the Run ID, pdf filename, task ID and pdfStatus (if any)
$.post({
url: "{% url 'runs' %}",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
id: thisId,
filename: filename,
task_id: taskID,
},
success: function(data) {
// Split the returned string to separate the task ID [0] from the status [1]
var taskID = data.split(";")[0];
var pdfStatus = data.split(";")[1];
// Convert the pdfStatus Python bools into JavaScript bools
if (pdfStatus == "False") {
pdfStatus = false;
} else if (pdfStatus == "True") {
pdfStatus = true;
};
if (!pdfStatus) {
console.log("Repeat function.");
downloadPdf(filename, taskID, pdfStatus);
} else {
console.log("Download PDF");
window.open("data:application/pdf;base64," + data);
};
},
traditional: true
}).done();
};
});
PDF 下载的实际 JavaScript 方面非常简单。我发送了我想要生成 PDF 的对象的 ID(“Run”),以及它应该具有的文件名(这是在 get同一页面的 Django 视图的一部分)和一个空的 celery 任务 ID(当然,该任务尚未创建)。我得到的响应是一个由“celery task ID”组成的字符串;如果任务尚未完成,则为 False,因此我重复 POST 请求。
在后端,我根据任务 ID 是否存在来处理 POST 请求:
def post(self, request):
# Get the args from the incoming request
run_id = request.POST.get('id')
filename = request.POST.get('filename')
task_id = request.POST.get('task_id')
if run_id and task_id == "None":
# Database and Django stuff happens here for a few lines...
# Fire off a Celery task to generate the PDF file asynchronously
pdf_task = create_pdf.delay(sensor, range_period)
response_string = str(pdf_task.task_id) + ";" + str(AsyncResult(pdf_task.task_id).ready())
return HttpResponse(response_string)
elif task_id != "None":
pdf_done = AsyncResult(task_id).ready() # If this is false, send the task ID back with a False
if not pdf_done:
response_string = str(task_id) + ";" + str(pdf_done)
return HttpResponse(response_string)
# Otherwise send the PDF back
else:
pdf_task = AsyncResult(task_id)
pdf_file = pdf_task.result
pdf_file_location = settings.MEDIA_ROOT + '/reports/' + pdf_file
# response = HttpResponse(content_type='application/pdf')
# response['Content-Disposition'] = 'attachment; filename={}'.format(pdf_task.result)
# # return response
try:
# with open(pdf_file_location, 'r') as pdf:
# response = HttpResponse(pdf.read(), content_type='application/pdf')
# response['Content-Disposition'] = 'attachment; filename="' + pdf_task.result + '"'
# pdf.close()
return FileResponse(open(pdf_file_location, 'rb'), content_type='application/pdf')
except IOError:
print("File does not exist, check above.")
return response
我已经继续尝试使文件下载与 AJAX 请求一起工作。到目前为止,没有被注释掉的那个实际上已经返回了一串编码文本到前端,但我不知道如何解码,我最终得到一个看起来像这样的选项卡:
因此,在文件处理完成后,编码的 PDF 将到达前端(那部分很好),但我在 JavaScript 方面还不够好,无法弄清楚如何将编码的字符串转换为 PDF 文件。
【问题讨论】:
标签: javascript jquery ajax django pdf