• 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: stderr:

    '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:wkwkhtmltopdfinwkhtmltopdf.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:wkwkhtmltopdfinwkhtmltoimage.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 BarryvdhSnappyFacadesSnappyPdf 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');
    踩过这个坑,还有下一个坑等着你,这一路就是给自己填坑,坑填多了,也就习惯了,直到这一路平坦了,也就无怨无悔了。
  • 相关阅读:
    pandas isin 和not in
    游戏开发需要学什么?
    打开页面,数字会自增的效果怎么弄?
    jq 导航栏点击添加/删除类(a标签跳转页面)
    bootstrap+jq分页
    2020/12/18
    2020/12/17
    2020/12/16
    2020/12/15
    2020/12/14
  • 原文地址:https://www.cnblogs.com/xiaofeilin/p/13561020.html
Copyright © 2020-2023  润新知