【问题标题】:Laravel How to create and download PDF from view on same routeLaravel 如何从同一路线的视图中创建和下载 PDF
【发布时间】:2020-01-08 20:43:55
【问题描述】:

我有一个laravel-应用程序,我想从值生成 PDF,用户已在某些输入字段中输入。因此,当用户输入数据时,他单击一个生成 PDF 的按钮,然后立即自动下载。 所有这些都应该发生在同一条路线/视图上。 PDF 不应存储在某处。

所以现在,当我单击按钮时,输入的数据会通过,例如存储在数据库中,似乎创建了一个 PDF,但我看不到或找不到它,而且我的浏览器没有通知我有 PDF 可供下载。

在开始之前,我安装了laravel-dompdf-plugin,并按照说明进行操作。

所以我的路线是这样的

Route::view('formpage', 'app.statement')->name('statement'); // The blade view with the Form

Route::post('statement', 'MyController@generatePDF')->name('generatePDF'); // this is where I post the form

这是我的控制器

use PDF;

class MyController extends Controller {

  public function generatePDF(Request $request){

    $statement = Statement::create([
        'name' => $validated['name'],
        'email' => $validated['email'],
        'phone' => $validated['phone'],
        'declaration_date' => $validated['declaration_date'],
    ]);

    $pdf = PDF::loadView('pdf.statement', $statement);

    return $pdf->download('File__'.$statement->name.'.pdf');

  }

}

我通过使用axios 来发布带有javascript 的表单,只需这样做:

$('#submitBtn').click(function(e) {
  const formData = new FormData();

  formData.append(
     "name",
     $("#statement")
        .find('input[name="name"]')
        .val()
   );

   ...etc with all other fields

  axios.post($("#statement form").attr("action"), formData)
            .then(response => {
               $('#submitBtn')
                    .attr("disabled", "disabled")
                    .addClass("disabled")
                    .html('<i class="fas fa-fw fa-check"></i> Success'); */
                $("#statement form")[0].reset();
            })
            .catch(error => {
                console.log("ERR: ", error); // DEBUG

                $("#statement .text-danger").show();

                $('#sworn-statement button[type="submit"]')
                    .removeAttr("disabled")
                    .removeClass("disabled")
                    .html("Send");
            });

}

我做错了什么?

更新

我尝试过这样做:

const FileDownload = require("js-file-download");

axios.post($("#statement form").attr("action"), formData)
     .then(response => {
          FileDownload(response.data,"File.pdf");
     }).catch(error => {
         console.log('error:', error); 
     });

这给了我一个空白页。

【问题讨论】:

  • 您正在使用 javascript 将请求发布到 statement 路由?如果是这样,您需要发布对这个问题至关重要的 javascript 代码。如果您将浏览器导航到页面上,它就会起作用,因为他将内容类型的 pdf 作为响应并知道如何处理它。如果你用 js 异步发布你的东西,浏览器不知道发生了什么,因为他只是得到一个带有 pdf 的响应对象,如果你不在那里处理它,它将被忽略。
  • @thmspl 我已经更新了我的问题 - 添加了 js 代码
  • 由于您是通过 javascript 创建请求,因此结果也来自 javascript。因此下载可能不会被触发,因为它作为 AJAX 响应返回。您可能需要将传入的数据转换为文件并通过 JS 触发下载,这是一个示例如何 blog.jayway.com/2017/07/13/open-pdf-downloaded-api-javascript 。响应可能不是 blob 格式,所以也要小心。

标签: php laravel dompdf


【解决方案1】:

正如我在 cmets 中所说,您的问题是该文件位于您从 axios POST 请求获得的响应中。如果您在收到响应后不处理文件下载,则不会发生任何事情。

您可以使用js-file-download 模块。安装此模块后,您可以将代码修改为以下内容:

const FileDownload = require('js-file-download');

axios.get(YOUR_URL)
   .then((response) => {
        FileDownload(response.data, YOUR_FILE_NAME);
   });

我还从that answer 获得了另一个使用 JQuery 的解决方案:

$.ajax({
    type: "POST",
    url: url,
    data: params,
    success: function(response, status, xhr) {
        // check for a filename
        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }

        var type = xhr.getResponseHeader('Content-Type');
        var blob = new Blob([response], { type: type });

        if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
            window.navigator.msSaveBlob(blob, filename);
        } else {
            var URL = window.URL || window.webkitURL;
            var downloadUrl = URL.createObjectURL(blob);

            if (filename) {
                // use HTML5 a[download] attribute to specify filename
                var a = document.createElement("a");
                // safari doesn't support this yet
                if (typeof a.download === 'undefined') {
                    window.location = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location = downloadUrl;
            }

            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
        }
    }
});

只需将 urlparams 属性替换为您的内容即可。这还会创建一个POST 请求,并在响应到达后将传入的 PDF 文件作为文件下载处理。

【讨论】:

  • 第一种方法,给我一个空白页... :-/
  • 控制台出错了?
  • 嗯不...但是response.data 有点胡言乱语...控制器可能返回错误吗?
  • 你用的是jquery还是axios代码? “胡言乱语”的东西是您的 PDF 作为二进制文件。所以不用担心。
  • 请用您当前使用的代码更新您的问题。
猜你喜欢
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
相关资源
最近更新 更多