【问题标题】:JavaScript/jQuery downloading PDF file returned from Django viewJavaScript/jQuery 下载从 Django 视图返回的 PDF 文件
【发布时间】: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


    【解决方案1】:

    您可以将 base64 解码为 Blob 并将其下载为文件。

    var blob = new Blob(atob(data), {type: 'application/pdf'})
    
    var link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = "filename.pdf";
    document.body.appendChild(link);
    link.click()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-04
      • 1970-01-01
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 2013-07-23
      相关资源
      最近更新 更多