当前位置:   article > 正文

vue处理PDF文档流数据并实现PDF的预览以及打印功能以及处理PDF打印乱码问题_vue打印pdf流文件

vue打印pdf流文件

VUE项目处理PDF文档流数据并实现PDF的预览以及打印功能以及处理PDF打印乱码问题

1.业务需求:
  • vue项目需要对后端返回的PDF文档流数据进行处理,在前端实现处理后的PDF文件的预览以及打印功能,最后再处理PDF页面打印乱码问题。
2.需求分析:
  • 首先由于后端返回的是文档流数据,所以第一步要将文档流数据转换为正确的PDF格式的数据,第二步是要将转化的PDF数据在页面上进行预览(这里我使用的是vue-pdf插件),最后是要在预览的PDF页面上添加打印按钮以及实现打印功能(PDF打印功能vue-pdf插件里面有方法提供,不用再单独去引入外部的打印插件)。另外由于vue-pdf插件使用的是iframe进行渲染,所以存在乱码问题,所以需要对其源文件进行修改。
3.解决方案:
  • 第1步是处理后端返回的文档流数据(注意:请求PDF文档流数据的接口时如果是axios封装的post请求注意使用params,{responseType:'blob'},如果是axios封装的get请求注意使用{params:params,responseType:'blob'},否则文档流解析会报错,或者解析出来是一片空白):

  •       // 将返回的流数据转换为url(data: 文档流数据)
            getObjectURL(data) {
              let url = null
              let file = new Blob([data],{type:'application/pdf;chartset=utf-8'})
              if (window.createObjectURL != undefined) {
                  // 通用
                url = window.createObjectURL(file)
              } else if (window.webkitURL != undefined) {
                  // 兼容谷歌
                try {
                  url = window.webkitURL.createObjectURL(file)
                } catch (error) {
      
                }
              } else if (window.URL != undefined) {
                  // 兼容其他
                try {
                  url = window.URL.createObjectURL(file)
              } catch (error) {
    
                }
              }
                // 将转化后url赋值
              this.pdfUrl = url
            },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 第2步是下载及引入vue-pdf:

  •   // 首先是安装vue-pdf
      npm install --save vue-pdf
    
    • 1
    • 2
  • // 在页面引入
    import pdf from 'vue-pdf'
    components: {
          pdf,
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 第3步是将转化好的PDF数据通过vue-pdf插件进行预览及打印:

    <div v-if="src" style="overflow-y: auto;overflow-x: hidden;">
        <!--打印直接调用vue-pdf里面的方法-->
            <el-button type="primary" @click="$refs.pdf.print()" size="mini">打印</el-button>
            <el-button type="warning" plain @click="viewDia = false" size="mini">关闭</el-button>
            <div>
              <pdf
                ref="pdf"
                :src="pdfUrl"
              ></pdf>
            </div>
          </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 第四部是处理PDF打印乱码问题:

  • 详情可参考https://github.com/FranckFreiburger/vue-pdf/pull/130/commits/253f6186ff0676abf9277786087dda8d95dd8ea7

  • 解决方法是修改pdfjsWrapper.js文件(索引:node_modules => vue-pdf => src => pdfjsWrapper.js)

  • 最后附上我这边最新的修改的pdfjsWrapper.js全部内容(亲测无误,可直接复制):

  •   import { PDFLinkService } from 'pdfjs-dist/es5/web/pdf_viewer';
      
      var pendingOperation = Promise.resolve();
      
      export default function(PDFJS) {
      
      	function isPDFDocumentLoadingTask(obj) {
      
      		return typeof(obj) === 'object' && obj !== null && obj.__PDFDocumentLoadingTask === true;
      		// or: return obj.constructor.name === 'PDFDocumentLoadingTask';
      	}
      
      	function createLoadingTask(src, options) {
      
      		var source;
      		if ( typeof(src) === 'string' )
      			source = { url: src };
      		else if ( src instanceof Uint8Array )
      			source = { data: src };
      		else if ( typeof(src) === 'object' && src !== null )
      			source = Object.assign({}, src);
      		else
      			throw new TypeError('invalid src type');
      
      		// source.verbosity = PDFJS.VerbosityLevel.INFOS;
      		// source.pdfBug = true;
      		// source.stopAtErrors = true;
      
      		var loadingTask = PDFJS.getDocument(source);
      		loadingTask.__PDFDocumentLoadingTask = true; // since PDFDocumentLoadingTask is not public
      
      		if ( options && options.onPassword )
      			loadingTask.onPassword = options.onPassword;
      
      		if ( options && options.onProgress )
      			loadingTask.onProgress = options.onProgress;
      
      		return loadingTask;
      	}
      
      
      	function PDFJSWrapper(canvasElt, annotationLayerElt, emitEvent) {
      
      		var pdfDoc = null;
      		var pdfPage = null;
      		var pdfRender = null;
      		var canceling = false;
      
      		canvasElt.getContext('2d').save();
      
      		function clearCanvas() {
      
      			canvasElt.getContext('2d').clearRect(0, 0, canvasElt.width, canvasElt.height);
      		}
      
      		function clearAnnotations() {
      
      			while ( annotationLayerElt.firstChild )
      				annotationLayerElt.removeChild(annotationLayerElt.firstChild);
      		}
      
      		this.destroy = function() {
      
      			if ( pdfDoc === null )
      				return;
      
      			// Aborts all network requests and destroys worker.
      			pendingOperation = pdfDoc.destroy();
      			pdfDoc = null;
      		}
      
      		this.getResolutionScale = function() {
      
      			return canvasElt.offsetWidth / canvasElt.width;
      		}
      
      		this.printPage = function(dpi, pageNumberOnly) {
      
      			if ( pdfPage === null )
      				return;
      
      			// 1in == 72pt
      			// 1in == 96px
      			var PRINT_RESOLUTION = dpi === undefined ? 150 : dpi;
      			var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
      			var CSS_UNITS = 96.0 / 72.0;
      
      			// var iframeElt = document.createElement('iframe');
            var printContainerElement = document.createElement('div');
            printContainerElement.setAttribute('id', 'print-container')
      			// function removeIframe() {
            //
      			// 	iframeElt.parentNode.removeChild(iframeElt);
      			// }
            function removePrintContainer() {
              printContainerElement.parentNode.removeChild(printContainerElement);
            }
      
      			new Promise(function(resolve, reject) {
      
      				// iframeElt.frameBorder = '0';
      				// iframeElt.scrolling = 'no';
      				// iframeElt.width = '0px;'
      				// iframeElt.height = '0px;'
      				// iframeElt.style.cssText = 'position: absolute; top: 0; left: 0';
              //
      				// iframeElt.onload = function() {
              //
      				// 	resolve(this.contentWindow);
      				// }
              //
      				// window.document.body.appendChild(iframeElt);
              printContainerElement.frameBorder = '0';
              printContainerElement.scrolling = 'no';
              printContainerElement.width = '0px;'
              printContainerElement.height = '0px;'
              printContainerElement.style.cssText = 'position: absolute; top: 0; left: 0';
      
              window.document.body.appendChild(printContainerElement);
              resolve(window)
      			})
      			.then(function(win) {
      
      				win.document.title = '';
      
      				return pdfDoc.getPage(1)
      				.then(function(page) {
      
      					var viewport = page.getViewport({ scale: 1 });
      					// win.document.head.appendChild(win.document.createElement('style')).textContent =
                printContainerElement.appendChild(win.document.createElement('style')).textContent =
      						'@supports ((size:A4) and (size:1pt 1pt)) {' +
      							'@page { margin: 1pt; size: ' + ((viewport.width * PRINT_UNITS) / CSS_UNITS) + 'pt ' + ((viewport.height * PRINT_UNITS) / CSS_UNITS) + 'pt; }' +
      						'}' +
                  '#print-canvas { display: none }' +
      						'@media print {' +
      							'body { margin: 0 }' +
      							// 'canvas { page-break-before: avoid; page-break-after: always; page-break-inside: avoid }' +
                  '#print-canvas { page-break-before: avoid; page-break-after: always; page-break-inside: avoid; display: block }' +
                  'body > *:not(#print-container) { display: none; }' +
      						'}'+
      
      						'@media screen {' +
      							'body { margin: 0 }' +
      						'}'
      					return win;
      				})
      			})
      			.then(function(win) {
      
      				var allPages = [];
      
      				for ( var pageNumber = 1; pageNumber <= pdfDoc.numPages; ++pageNumber ) {
      
      					if ( pageNumberOnly !== undefined && pageNumberOnly.indexOf(pageNumber) === -1 )
      						continue;
      
      					allPages.push(
      						pdfDoc.getPage(pageNumber)
      						.then(function(page) {
      
      							var viewport = page.getViewport({ scale: 1 });
      
      							// var printCanvasElt = win.document.body.appendChild(win.document.createElement('canvas'));
                    var printCanvasElt = printContainerElement.appendChild(win.document.createElement('canvas'));
                    printCanvasElt.setAttribute('id', 'print-canvas')
      							printCanvasElt.width = (viewport.width * PRINT_UNITS);
      							printCanvasElt.height = (viewport.height * PRINT_UNITS);
      
      							return page.render({
      								canvasContext: printCanvasElt.getContext('2d'),
      								transform: [ // Additional transform, applied just before viewport transform.
      									PRINT_UNITS, 0, 0,
      									PRINT_UNITS, 0, 0
      								],
      								viewport: viewport,
      								intent: 'print'
      							}).promise;
      						})
      					);
      				}
      
      				Promise.all(allPages)
      				.then(function() {
      
      					win.focus(); // Required for IE
      					if (win.document.queryCommandSupported('print')) {
      						win.document.execCommand('print', false, null);
      						} else {
      						win.print();
      					  }
      					// removeIframe();
                removePrintContainer();
      				})
      				.catch(function(err) {
      
      					// removeIframe();
                removePrintContainer();
      					emitEvent('error', err);
      				})
      			})
      		}
      
      		this.renderPage = function(rotate) {
      			if ( pdfRender !== null ) {
      
      				if ( canceling )
      					return;
      				canceling = true;
      				pdfRender.cancel();
      				return;
      			}
      
      			if ( pdfPage === null )
      				return;
      
      			var pageRotate = (pdfPage.rotate === undefined ? 0 : pdfPage.rotate) + (rotate === undefined ? 0 : rotate);
      
      			var scale = canvasElt.offsetWidth / pdfPage.getViewport({ scale: 1 }).width * (window.devicePixelRatio || 1);
      			var viewport = pdfPage.getViewport({ scale: scale, rotation:pageRotate });
      
      			emitEvent('page-size', viewport.width, viewport.height, scale);
      
      			canvasElt.width = viewport.width;
      			canvasElt.height = viewport.height;
      
      			pdfRender = pdfPage.render({
      				canvasContext: canvasElt.getContext('2d'),
      				viewport: viewport
      			});
      
      			annotationLayerElt.style.visibility = 'hidden';
      			clearAnnotations();
      
      			var viewer = {
      				scrollPageIntoView: function(params) {
      					emitEvent('link-clicked', params.pageNumber)
      				},
      			};
      
      			var linkService = new PDFLinkService();
      			linkService.setDocument(pdfDoc);
      			linkService.setViewer(viewer);
      
      			pendingOperation = pendingOperation.then(function() {
      
      				var getAnnotationsOperation =
      				pdfPage.getAnnotations({ intent: 'display' })
      				.then(function(annotations) {
      
      					PDFJS.AnnotationLayer.render({
      						viewport: viewport.clone({ dontFlip: true }),
      						div: annotationLayerElt,
      						annotations: annotations,
      						page: pdfPage,
      						linkService: linkService,
      						renderInteractiveForms: false
      					});
      				});
      
      				var pdfRenderOperation =
      				pdfRender.promise
      				.then(function() {
      
      					annotationLayerElt.style.visibility = '';
      					canceling = false;
      					pdfRender = null;
      				})
      				.catch(function(err) {
      
      					pdfRender = null;
      					if ( err instanceof PDFJS.RenderingCancelledException ) {
      
      						canceling = false;
      						this.renderPage(rotate);
      						return;
      					}
      					emitEvent('error', err);
      				}.bind(this))
      
      				return Promise.all([getAnnotationsOperation, pdfRenderOperation]);
      			}.bind(this));
      		}
      
      
      		this.forEachPage = function(pageCallback) {
      
      			var numPages = pdfDoc.numPages;
      
      			(function next(pageNum) {
      
      				pdfDoc.getPage(pageNum)
      				.then(pageCallback)
      				.then(function() {
      
      					if ( ++pageNum <= numPages )
      						next(pageNum);
      				})
      			})(1);
      		}
      
      
      		this.loadPage = function(pageNumber, rotate) {
      
      			pdfPage = null;
      
      			if ( pdfDoc === null )
      				return;
      
      			pendingOperation = pendingOperation.then(function() {
      
      				return pdfDoc.getPage(pageNumber);
      			})
      			.then(function(page) {
      
      				pdfPage = page;
      				this.renderPage(rotate);
      				emitEvent('page-loaded', page.pageNumber);
      			}.bind(this))
      			.catch(function(err) {
      
      				clearCanvas();
      				clearAnnotations();
      				emitEvent('error', err);
      			});
      		}
      
      		this.loadDocument = function(src) {
      
      			pdfDoc = null;
      			pdfPage = null;
      
      			emitEvent('num-pages', undefined);
      
      			if ( !src ) {
      
      				canvasElt.removeAttribute('width');
      				canvasElt.removeAttribute('height');
      				clearAnnotations();
      				return;
      			}
      
      			// wait for pending operation ends
      			pendingOperation = pendingOperation.then(function() {
      
      				var loadingTask;
      				if ( isPDFDocumentLoadingTask(src) ) {
      
      					if ( src.destroyed ) {
      
      						emitEvent('error', new Error('loadingTask has been destroyed'));
      						return
      					}
      
      					loadingTask = src;
      				} else {
      
      					loadingTask = createLoadingTask(src, {
      						onPassword: function(updatePassword, reason) {
      
      							var reasonStr;
      							switch (reason) {
      								case PDFJS.PasswordResponses.NEED_PASSWORD:
      									reasonStr = 'NEED_PASSWORD';
      									break;
      								case PDFJS.PasswordResponses.INCORRECT_PASSWORD:
      									reasonStr = 'INCORRECT_PASSWORD';
      									break;
      							}
      							emitEvent('password', updatePassword, reasonStr);
      						},
      						onProgress: function(status) {
      
      							var ratio = status.loaded / status.total;
      							emitEvent('progress', Math.min(ratio, 1));
      						}
      					});
      				}
      
      				return loadingTask.promise;
      			})
      			.then(function(pdf) {
      
      				pdfDoc = pdf;
      				emitEvent('num-pages', pdf.numPages);
      				emitEvent('loaded');
      			})
      			.catch(function(err) {
      
      				clearCanvas();
      				clearAnnotations();
      				emitEvent('error', err);
      			})
      		}
      
      		annotationLayerElt.style.transformOrigin = '0 0';
      	}
      
      	return {
      		createLoadingTask: createLoadingTask,
      		PDFJSWrapper: PDFJSWrapper,
      	}
      }.then(function(pdf) {
      
      				pdfDoc = pdf;
      				emitEvent('num-pages', pdf.numPages);
      				emitEvent('loaded');
      			})
      			.catch(function(err) {
      
      				clearCanvas();
      				clearAnnotations();
      				emitEvent('error', err);
      			})
      		}
      
      		annotationLayerElt.style.transformOrigin = '0 0';
      	}
      
      	return {
      		createLoadingTask: createLoadingTask,
      		PDFJSWrapper: PDFJSWrapper,
      	}
      }
      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
  • 统一说明:最近有码友反馈修改pdfjsWrapper.js不生效,这里大家注意一下vue-pdf版本不要太高了,参考我使用的4.2.0版本,不然会有问题。

  • 解决

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/305618
推荐阅读
相关标签
  

闽ICP备14008679号