JavaScript / jQuery, загружающий файл PDF, возвращенный из представления Django - PullRequest
0 голосов
/ 23 апреля 2019

У меня есть задача сельдерея, которая создает 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();
    };
});

Фактическая сторона JavaScript загрузки PDF достаточно проста.Я отправляю идентификатор объекта, который я хочу сгенерировать в формате PDF (« Run »), вместе с именем файла, которое должно иметь (это создается на части get вид Django на той же странице) и пустой идентификатор задачи сельдерея (задача, конечно, еще не была создана).Ответ, который я получаю, представляет собой строку из «идентификатора задачи сельдерея»;с False, если задача еще не выполнена, поэтому я повторяю запрос POST.

С серверной стороны я обрабатываю запрос 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.Пока что тот, который не закомментирован, на самом деле возвратил строку кодированного текста во внешний интерфейс, но я не уверен, как его декодировать, в итоге я получаю вкладку, которая выглядит следующим образом:

enter image description here

Итак, закодированный PDF-файл достигает внешнего интерфейса после обработки файла (эта часть в порядке), но я недостаточно хорош в JavaScript, чтобы понять, какпревратить закодированную строку в файл PDF.

1 Ответ

0 голосов
/ 23 апреля 2019

Вы можете декодировать 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...