背景:合同(后台返回pdf流文件)展示、下载、打印,基于angular4

场景区分:

1、checkout页面 —— post接口,入参为offering、shippingInfo、invoice等(body),返回生成合同的pdf流文件;

2、orderList、orderDetail页面 —— get接口,入参contentId(生成合同在内容管理保存对应的id,url),返回对应合同的pdf流文件。

需求补充说明:

在一个弹出dialog,合同展示在中间部分,footer部分为 下载、打印等按钮。

实现核心:

1、展示:

1> package.json中

  "dependencies": {

   "ng2-pdf-viewer": "^3.0.8",

   "pdfjs-dist": "^1.9.426" 

}

2> html

展示:

  <pdf-viewer *ngIf ="contract.stc" [src]="contract.src" [render-text]="true"  (after-load-complete)="afterLoadComplete($event)" (error)="loadContractError($event)" ></pdf-viewer>

下载:

  <a id="contract_download" class="fl mar1d5r mat6" [href]='sanitize(contract.src)' [download]="contract.name" *ngIf="contract.isLoadSuccess" >
    <svg class="hlds-icon fillWhite icon2r">
      <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="./assets/theme/default/icons/omniIcon-sprite/svg/symbols.svg#downLoad"></use>
    </svg>
  </a>

打印:
  <a class="fl mat6" (click)="print()" *ngIf="contract.isLoadSuccess">
    <svg class="hlds-icon fillWhite icon2r" >
      <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="./assets/theme/default/icons/omniIcon-sprite/svg/symbols.svg#print"></use>
    </svg>
  </a>
  <iframe #iframe [src]="contract.url" style='display:none;' *ngIf="contract.isLoadSuccess" ></iframe>

3>ts文件

  import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges, ViewChild, ElementRef } from '@angular/core';
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

  import { ConstantService } from '../../../../service/constant.service';
  import { MessageService } from "../../../../service/message.service";
  import { NormalHttpService } from "../../../../service/normal-http.service";

  import { SmartrecCommonService } from '../../../bizcommon/service/smartrec.service';
  import { OrderService } from '../../service/order.service';

  declare var $: any;

  @Component({
    selector: 'app-order-contract',
    templateUrl: './contract.component.html',
    styleUrls: ['./contract.component.css']
   })
  export class ContractComponent implements OnInit, OnChanges {
    /*contractInfo : any = {
      isGenerated : true,
      orderId: '',
      orderInfo : {} //the param that generate contract
    }*/
  @ViewChild('iframe') iframe: ElementRef;
  @Input() contractInfo : any ;
  @Output() acceptContractState = new EventEmitter<any>();

  contract : any = {
    src : '',
    url : '',
    totalPage : 1,
    page : 1,
    isLoading : true,
    isLoadSuccess: false
  }

  constructor(
   private sanitizer: DomSanitizer,
   private messageService: MessageService,
   private normalHttpService: NormalHttpService,
   private smartrecCommonService: SmartrecCommonService,
   private orderService: OrderService
  ) { }

  ngOnInit() {
  }

  ngOnChanges(change: SimpleChanges) {
    if(this.contractInfo && this.contractInfo.isGenerated && change.contractInfo.currentValue.orderInfo){
     this.contract.isLoadSuccess = false;
     this.generateContract();
      }
    if(this.contractInfo && !this.contractInfo.isGenerated && this.contractInfo.orderId) {
      this.queryContract();
    }
  }

  generateContract() {
   if(!this.contract.isLoadSuccess){
    this.contract.src = '';
    this.contract.isLoading = true;
    let header = this.normalHttpService.expandHeader({}, true);
    let url = this.normalHttpService.makeRequestUrl(`/order/order/${ConstantService.API_VERSION}/contract`);
    let xhr = new XMLHttpRequest();
    xhr.open("POST", url, true);
    xhr.responseType = "blob";
    for(let key in header) {
      xhr.setRequestHeader(key, header[key]);
    }
    xhr.send(JSON.stringify(this.contractInfo.orderInfo));
    xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      let blob = new Blob([xhr.response], {type: 'application/pdf'});
      this.contract.src = URL.createObjectURL(blob);
      this.contract.name = 'contract.pdf';
      this.contract.url = this.sanitizer.bypassSecurityTrustResourceUrl(this.contract.src);
    }
  }.bind(this);
  }
}

  queryContract() {
   this.contract.src = '';
   this.orderService.queryContractId(this.contractInfo.orderId).then((res) => {
    if (res.code !== 0) {
      this.messageService.errorAlert('Query contractId is failed !');
      return;
    }
    if (res.data.contentId) {
      this.contract.src = this.smartrecCommonService.getContentUrlById(res.data.contentId);
    }
   })
  }

  afterLoadComplete(pdf: any) {
    this.contract.totalPage = pdf.pdfInfo.numPages;
    this.contract.isLoading = false;
    this.contract.isLoadSuccess = true;
  }

  loadContractError(event: any) {
    this.contract.isLoading = false;
    this.contract.isLoadSuccess = false;
    this.messageService.errorAlert('Contract failed to load !');
  }

  agree() {
    this.acceptContractState.emit({
      isAgree : true,
      isLoadSuccess : this.contract.isLoadSuccess
    })
  }

  disAgree() {
    this.acceptContractState.emit({
      isAgree : false,
      isLoadSuccess : this.contract.isLoadSuccess
    })
  }

  print() {
    let getMyFrame = this.iframe.nativeElement.contentWindow || this.iframe.nativeElement.contentDocument;
    getMyFrame.print();
  }

  changePage(event) {
   const pageHeight = $('.ng2-pdf-viewer-container').height() / this.contract.totalPage;
   this.contract.page = Math.ceil($(event.target).scrollTop()/pageHeight);
  }

  sanitize(url:string){
    return this.sanitizer.bypassSecurityTrustUrl(url);
  }
}

备注:

1.打印内容在弹框内如何实现:首先,打印调用的是window.print()方法。利用iframe标签,将弹框内容的路径,转移到iframe的src属性上,相当于为打印内容新开辟了一个window,最后回归到调用window.print()方法。

参考:
1.https://github.com/VadimDez/ng2-pdf-viewer //展示打印思路

2.https://stackoverflow.com/questions/38457662/iframe-inside-angular2-component-property-contentwindow-does-not-exist-on-typ/50508477 //pdf局部打印思路

3.http://kriscan.oschina.io/blog/2017/05/26/20170526/  //链接安全问题解决

拓展:

1.如何将html内容转换为pdf:a.html2cavas将页面内容screenshot下来;b.jsPdf将screenshot转换为pdf。




pdf流文件的展示、下载、打印;html转为pdf的更多相关文章

  1. pdf流文件转图片

    需求:将后台返回的pdf流文件转换成图片与页面其他内容一起打印pdf流文件不能直接在前台显示,需要借助pdf.js+viewer.js. 一般情况下,如果要打印pdf流文件,可以直接在新打开的view ...

  2. 在.net Core 使用PDF模板文件生成PDF文件,代替WEB打印控件!

    这几天找WEB打印控件,要么收费的,要么免费的只能在IE里用! 我只想简单的打个标签纸!百度2天,看到一老兄说可以用PDF,然后又开始百度..找到了一篇文章 http://www.jianshu.co ...

  3. xilinx Vivado的使用详细介绍(2):创建工程、添加文件、综合、实现、管脚约束、产生比特流文件、烧写程序、硬件验证

    xilinx Vivado的使用详细介绍(2):创建工程.添加文件.综合.实现.管脚约束.产生比特流文件.烧写程序.硬件验证 Author:zhangxianhe 新建工程 打开Vivado软件,直接 ...

  4. C#/VB.NET 创建PDF/UA文件

    1.什么是PDF/UA文件 PDF/UA,即Universally Accessible PDF,该格式的PDF文件是于2012年8月以ISO标准14289-1发布的.具有普遍可访问的PDF文档标准. ...

  5. java转pdf(html转为pdf),解决中文乱码,标签不规范等问题

    第一步,下载jar包以及建对应的文件夹.注意pd4ml的jar要选择pro版本.然后建一个pd4fonts.properties 里面对应的字体. SimSun = simsun.ttf 前面为变量名 ...

  6. SAP 打印自动导出PDF本地文件(自己做的例子)

    smartforms导出PDF: 常用函数有: convert_otfconvert_otfspooljob_2_pdfconvert_abapspooljob_2_pdfCONVERT_OTF_2_ ...

  7. 打印信息,通过.jasper工具将集合输出到PDF文件 然后利用打印机打印文件

    我们上一次成功的利用iReport工具制作了一张报表,并且预览了报表最后的效果,也生成了格式为“jrpxml”.“jrxml”与“jasper”的文件.这次,我们使用jasper提供的java的api ...

  8. 如何打印加密的PDF文件?

    如何打印加密的PDF文件? Pdf加密了不让打印怎么办?? 下载Foxit PDF Editor以下是下载地址:http://www.orsoon.com/Soft/4865.html 用它打开加密的 ...

  9. go http 下载视频(TS码流文件)(推荐一个网站学习 go example)

    视频  http下载代码 dn.go(注意:代码很ugly,没怎么花时间) 总体感觉特别简单,网上看了下 net/http ,io这2个库的使用, 几分钟就写完了,感觉cpp 在做工具这块 开发效率的 ...

随机推荐

  1. 其它 nginx

    原地址忘了 常用命令: 在CMD下输入如下命令,可以强行关闭所有Nginx进程 taskkill /f /im nginx.exe start nginx nginx -s stop nginx -s ...

  2. 定时器&改变定时器的执行频率

    static System.Threading.Timer timer; static void Main(string[] args) { Console.WriteLine("Press ...

  3. python之字符串拼接:%和format

    使用百分号拼接字符串: 例如: msg='i am %s my hobby is...' %'abc' print(msg) 如果需要用2个%s呢?就使用括号例如: msg='I am %s my h ...

  4. poj3250(单调栈模板题)

    题目链接:https://vjudge.net/problem/POJ-3250 题意:求序列中每个点右边第一个>=自身的点的下标. 思路:简单介绍单调栈,主要用来求向左/右第一个小于/大于自身 ...

  5. 【Android端】【日志收集上报SDK相关内容测试的方案梳理总结】

    测试方案: 主要从几个方面关注,功能 性能 服务端策略(目前所有的这些上报收集等都会通过开关的精细化,通过接口方式将信息返回给APP端,APP端根据相关内容进行上报,因此基于此的上报机制及收集机制都需 ...

  6. paloalto防火墙接口使用方法及实例

    1.获取账号相关的唯一API KEY windows:https://x.x.x.x/api/?type=keygen&user=username&password=password ...

  7. paloalto防火墙内存使用率高

    上述内存使用率是正常的,实际使用的是buffers.

  8. spring mvc 映射与适配器

    在深入学习Spring mvc 过程中,我们需要了解如下两个类: org.springframework.web.servlet.mvc.method.annotation.RequestMappin ...

  9. git log命令常用参数集合

    git log 查看 提交历史 默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面. 常用的格式占位符写法及其代表的意义.选项 说明%H 提交对象(commit)的 ...

  10. Vue 获取元素样式 元素高度

    看到这个问题我第一时间想的竟然是JS 不知道你是怎么想的 不过昨天有一个小哥哥 问我一个Vue的 哈哈哈 get了 我当时问他为什么不用JS获取 他说 这个性能更高 那我们来看看这个高性能的获取元素高 ...