Проблема в отображении FileResponse, содержащем сгенерированный pdf, на web-странице в теге <embed>
Всем доброго времени суток. Пишется приложение на django, которое должно из введенных в форму на странице данных, на этой же странице отобразить сгенерированный с помощью reportlab pdf-файл. Страница разбита на два блока с помощью колонок bootstrap, во второй колонке есть элемент c пустым параметром src По нажатию на ссылку выполняется ajax запрос на сервер, который отсылает данные из формы, сервер (то бишь view на django), обрабатывает данные, формирует pdf в виде массива байтов (BytesIO) и отправляет результат в виде FileResponse. success в ajax'e принимает ответ, создает blob объект, на основе blob формирует ссылку на файл и присваивает эту ссылку параметру src . В итоге pdf файл отображается, но отображает белеберду (есть подозрения на неверное кодирование файла). Помогите советом, испробовал много вариантов. Есть нюанс, если присваивать {% url <ну и так далее> %} в параметр src, то все отображается верно, но нюанс в том, что таким способом нельзя передать значения формы в представление, так как поля формы динамические, и их количество и наличие всегда разное (детали создаваемого приложения, долго описывать). Отсюда вывод, что использование ajax обязательно, отталкиваться нужно от этого. Ниже приложу коды. страница:
{% block Content %}
<div class="container-fluid">
<div class="row">
<div class="col col-sm-6 col-md-6 col-lg-6">
<h2>{{ caption }}</h2>
<form class="form-control" method="post" id="document_form">
{% csrf_token %}
<span id="myForm">{{ form|crispy }}</span>
<button class="btn btn-success" type="submit">{{ caption }}</button>
<a class="btn btn-info" href={{ back_url }}>Назад</a>
<a class="btn btn-outline-success" href="#" onclick="updateFrame2()">Просмотр</a>
</form>
<a class="btn-danger" id="mybtn" href="#" onclick="get_pdf()">TEST</a>
</div>
<div class="col col-sm-6 col-md-6 col-lg-6">
<embed id="frameDoc" type="application/pdf" width="100%" height="100%" src="">
</embed>
</div>
</div>
</div>
{% endblock %}
{% block JavaScript %}
<script defer src="{% static 'js/jquery-3.7.1.js' %}"></script>
<script defer src="{% static 'js/print.js' %}"></script>
<script>
{# работает верно, но не подходит #}
function updateFrame2() {
document.getElementById(`frameDoc`).src = '{% url 'MyApp:MakeReport' %}';
};
function get_pdf() {
const formdata = $('#document_form').serialize();
$.ajax({
url: "http://127.0.0.1:8000/myapp/makereport/",
type: "POST",
data: $('#document_form').serialize(),
success: function(data) {
var blob = new Blob([data,], {type: 'application/pdf'});
let link = URL.createObjectURL(blob);
document.getElementById(`frameDoc`).src = link;
console.log('success');
},
error(jqXHR, exception) {
console.log('error');
},
});
};
</script>
{% endblock %}
view:
@xframe_options_exempt
def MakeReport(request):
# все приведенные манипуляции на самом деле не важны
# так как pdf() возвращает BytesIO(seek=0)
json = UserDocs.objects.get(id=1).make_json_with_parameters()
requisites = [Requisite(**req) for req in json]
pdf = PDFDocument()
for req in requisites:
pdf.add_requisite(req)
pdf.build_doc()
# единственный нюанс в том, что pdf нигде не хранится физически на диске,
# поэтому ссылку на файл тоже не получится сделать
return FileResponse(pdf(), as_attachment=False, filename='test.pdf')
Вопрос решен, спасибо всем за участие, решается так:
function get_pdf() {
const formdata = $('#document_form').serialize();
$.ajax({
url: "http://127.0.0.1:8000/privatecabinet/makereport/",
type: "POST",
data: $('#document_form').serialize(),
xhrFields: {
responseType: 'blob'
},
success: function(data) {
let link2 = URL.createObjectURL(data);
document.getElementById(`frameDoc`).src = link2;
console.log('success');
},
error(jqXHR, exception) {
console.log('error');
},
});
};