laravel使用snappy生成pdf問題及過程(本地環境)


1.安裝過程可以按照這里進行https://packagist.org/packages/barryvdh/laravel-snappy

其中要按裝好

"barryvdh/laravel-snappy": "0.4.7",
"h4cc/wkhtmltoimage-amd64": "0.12.x",
        "h4cc/wkhtmltopdf-amd64": "0.12.x",
wkhtmltopdf/wkhtmltoimage安裝在本地時,記得要添加環境變量(IDEA不同,wkhtmltopdf -V結果就可能不一樣,phpstorm可以,vscode不行(可能是我設置完環境變量沒有重啟電腦的原因)
),如下:
1.檢查是否安裝了wkhtmltopdf

2.若安裝,檢查是否配置了path的環境變量。可通過cmd輸入 wkhtmltopdf -V 來嘗試。

3.若環境變量以配置,測試下wkhtmltopdf是否能正常使用。可在cmd命令中輸入  wkhtmltopdf  www.baidu.com aaaaaa.pdf    點擊回車,cmd面板會顯示生成100%並且success,可以在user目錄下搜索aaaaaa.pdf,看是否存在。注意這里命令的第二個是網址,頁可以指定html文件,第三個是要生成的pdf名字,不要寫路徑,有時候路徑會生成失敗。

4.若以上都沒有問題,那么存在一個非常惡心的清空,就是IDEA檢測不到wkhtmltopdf的環境變量。可以在IDEA的Terminal中輸入

wkhtmltopdf -V 命令來檢查是否檢測到了環境變量。若是沒有那么就需要修改代碼了。

核心代碼如下:

String jsonData = JsonUtil.toJson(data);
String htmlStr = ResourceUtil.getResourceAsString("/import/import_preview_tpl.html");
htmlStr = htmlStr.replace("@{cdn}", mediaServer);
htmlStr = htmlStr.replace("@{data}", jsonData);
String htmlPath = FileUtil.randomTempFilePath(".html");
FileUtil.createStringFile(htmlPath, htmlStr);

// generate pdf
String pdfPath = FileUtil.randomTempFilePath(".pdf");
List<String> cmd = new ArrayList<>();
cmd.add("D:\\wkhtmltopdf\\bin\\wkhtmltopdf");//注意這里要指定自己的安裝目錄了
cmd.add("-s");
cmd.add("letter");
cmd.add("-T");
cmd.add("0");
cmd.add("-B");
cmd.add("0");
cmd.add("-L");
cmd.add("0");
cmd.add("-R");
cmd.add("0");
cmd.add(htmlPath);
cmd.add(pdfPath);
CmdUtil.executeCmd(cmd);
CmdUtil中的executeCmd方法:

public static void executeCmd(List<String> cmd) {
    try {
        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.redirectErrorStream(true);
        Process process = pb.start();
        BufferedReader errStreamReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = errStreamReader.readLine();
        while (line != null) {
            logger.info(line);
            line = errStreamReader.readLine();
        }
        process.waitFor();
    } catch (IOException e) {
        throw new LearningGenieRuntimeException("Execute cmd failed.", e);
    } catch (InterruptedException e) {
        throw new LearningGenieRuntimeException("Execute cmd failed.", e);
    }
}

2.問題一,The exit status code '1' says something went wrong:\nstderr:

'pdf' => [
        'enabled' => true,
        // 'binary'  => env('WKHTML_PDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
//        'binary'  => base_path('vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64'), //linux環境就可以用這個,如果是windows就會報錯
          'binary' => '"D:\wk\wkhtmltopdf\bin\wkhtmltopdf.exe"',  //單引號和雙引號,如果使用上一個就會報錯,windows環境用這個
        'timeout' => false,
        'options' => [],
        'env'     => [],
    ],
    
    'image' => [
        'enabled' => true,
        // 'binary'  => env('WKHTML_IMG_BINARY', '/usr/local/bin/wkhtmltoimage'),
//        'binary'  => base_path('vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64'),
          'binary' => '"D:\wk\wkhtmltopdf\bin\wkhtmltoimage.exe"',
        'timeout' => false,
        'options' => [],
        'env'     => [],
    ],
如果還是有問題,可能就是緩存了,進行一下清楚緩存(在terminal上打上
wkhtmltopdf -V  //允許該程序執行之后再執行下面清楚緩存
php artisan view:clear php artisan route:clear php artisan cache:clear php artisan config:clear
之后再重新生成pdf就可以了
問題二:

malformed utf-8 characters, possibly incorrectly encoded

電腦的語言設置問題:https://blog.csdn.net/qq_36025814/article/details/103439186

 

3.前后端配合生成pdf文件並且下載
前端:
printItem(item){
                webServices.get('/packaged',{responseType:'arraybuffer'})  //responseType: `arraybuffer` //一定要寫
                    .then(res => {
                        if (res.status == "200") {
                            let pdfUrl = window.URL.createObjectURL(new Blob([res.data], { type: `application/pdf` }));//word文檔為msword,pdf文檔為pdf
                            let fname = 'Invoice'; // 下載文件的名字
                            const link = document.createElement('a'); //創建一個a標簽
                            link.href = pdfUrl;
                            link.setAttribute('download', fname);
                            document.body.appendChild(link);
                            link.click(); //自動下載下載
                            // console.log(res.data)
                        }
                     })
}    

 

這是新建的blade視圖,即生成pdf的內容(pdf.blade.php)
<!
DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <table class="table table-striped"> <tr> <th>Row No.</th> <th>Entry ID</th> <th>DC</th> <th>Customer Name</th> <th>ID No.</th> <th>Referance No.</th> <th>Entry Purpose</th> <th>Time In</th> <th>Time Out</th> <th>Card No.</th> <th>Cabinets</th> <th>APC Card</th> <th>Key</th> </tr> @foreach ($assignees as $assignee) <tr> <td>{{ ++$i }}</td> <td>{{ $assignee->id }}</td> <td>{{ $assignee->datacenter }}</td> <td>{{ $assignee->cust->idnumber }}</td> <td>{{ $assignee->custidno}}</td> <td>{{ $assignee->refnumber }}</td> <td>{{ $assignee->entrypurpose}}</td> <td>{{ $assignee->timein }}</td> <td>{{ $assignee->timeout }}</td> <td>{{ $assignee->cardno }}</td> <td>{{ $assignee->cabinet }}</td> <td>{{ $assignee->apccard }}</td> <td>{{ $assignee->key }}</td> </tr> @endforeach </table> <div class="pull-right"> <strong> Report Generated on {{ date("d.m.Y") }} at {{date("h:i:sa")}} </strong> </body> </html>

后端:

use Barryvdh\Snappy\Facades\SnappyPdf as PDF;

$pdf = PDF::loadView('pdf',$data); //$data是pdf需要的一些數據值,即傳遞到pdf的變量
  return $pdf->setPaper('a4')->download('test.pdf');  //download可以在前端瀏覽器下載,save可以保存到磁盤,默認路徑是public文件夾中,使用stream()方法顯示在瀏覽器中
//使用save()的時候,在windows環境保存到具體位置時就沒有保存到,但是在網上查時說linux可以,


//在windows想保存到具體位置可以這樣
$pdf = PDF::loadView('pdf.invoice', $data);

Storage::put('public/pdf/invoice.pdf', $pdf->output());  //$pdf->output()為pdf文件流   public/pdf/invoice.pdf具體路徑
return $pdf->download('invoice.pdf');

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM