اشتراکها
آیندهی C++/CLI و NET Core 3.
- A bug is fixed in loop unroller which might lead to wrong condition codes being generated in the unrolled loop.
- Fixed a bug that caused ServiceHub.Host.CLR.x64 to stop working.
- Fixes issue in Chinese version of compiler errors C4533 and C2362 which resulted in incorrect order of string substitution for those languages.
- Improved stability of the Diagnostic Tools and Performance Profiler.
- Code generation problem causing crash with pure virtual destructor in const object
- Fixed a constant evaluation regression from 16.5 Preview 2
- Fixed an issue where MacOS couldn't be paired.
- Fixed an issue where the Diagnostic Tools while debugging and Performance Profiler fail to launch on XBox devices.
با توجه به اینکه فایلهای PDF نیز فایل باینری هستند، کلیات نکات مطلب «دریافت و نمایش تصاویر از سرور در برنامههای Angular» در مورد آنها هم صادق است. در اینجا به تکمیل این نکات پرداخته و مواردی را مانند ذخیره، چاپ و استفاده از اشیاء نمایشی <object>، <embed> و <iframe> نیز بررسی میکنیم. نمایش PDF در اینجا بر اساس امکانات توکار مرورگرها صورت میگیرد و نیاز به افزونهی اضافهتری ندارد.
کدهای سمت سرور دریافت فایل PDF
در اینجا کدهای سمت سرور برنامه، نکتهی خاصی را به همراه نداشته و صرفا یک فایل PDF ساده (محتوای باینری) را بازگشت میدهد:
که در نهایت با آدرس api/Reports/GetPdfReport در سمت کلاینت قابل دسترسی خواهد بود.
سرویس دریافت محتوای باینری در برنامههای Angular
برای اینکه HttpClient برنامههای Angular بتواند محتوای باینری را بجای محتوای JSON پیشفرض آن دریافت کند، نیاز است نوع خروجی سمت سرور آنرا به blob تنظیم کرد:
به این ترتیب پس از اشتراک به متد getReport این سرویس، اطلاعات باینری این فایل PDF را دریافت خواهیم کرد.
اصلاح Content Security Policy سمت سرور جهت ارائهی محتوای blob
پس از دریافت فایل PDF به صورت یک blob، با استفاده از متد URL.createObjectURL میتوان آدرس موقت محلی را برای دسترسی به آن تولید کرد و یک چنین آدرسهایی به صورت blob:http تولید میشوند. در این حالت در Content Security Policy سمت سرور، نیاز است امکان دسترسی به تصاویر و همچنین اشیاء از نوع blob را نیز آزاد معرفی کنید:
در غیراینصورت مرورگر نمایش یک چنین تصاویر و یا اشیایی را سد خواهد کرد.
دریافت فایلهای PDF از سرور و نمایش آنها در یک برنامهی Angular
پس از این مقدمات، کامپوننتی که یک فایل PDF را از سمت سرور دریافت کرده و نمایش میدهد، چنین کدی را خواهد داشت:
با این قالب:
- در اینجا در ngOnInit، به سرویس پنجره دسترسی یافته و وهلهای از آنرا جهت کار با متد createObjectURL شیء URL آن دریافت میکنیم.
- سپس مشترک متد getReport دریافت فایل PDF شده و اطلاعات نهایی آنرا به صورت pdfDataBlob دریافت میکنیم.
- این اطلاعات باینری را به متد createObjectURL ارسال کرده و آدرس موقتی این تصویر را در مرورگر بدست میآوریم.
- چون در این حالت Angular این URL را امن سازی میکند، یک چنین خروجی unsafe:blob بجای blob تولید خواهد شد که نمایش این مورد نیز توسط مرورگر سد میشود. برای رفع این مشکل، میتوان از سرویس DomSanitizer آن که به سازندهی کلاس تزریق شدهاست استفاده کرد:
تفاوت این مورد با حالت نمایش تصویر، استفاده از متد bypassSecurityTrustResourceUrl بجای متد bypassSecurityTrustUrl است. از این جهت که اشیاء یاد شده نیاز به SafeResourceUrl دارند و نه SafeUrl.
اینبار یک چنین انتسابی به صورت مستقیم کار میکند که سه نمونهی این انتساب را به اشیاء iframe ،object و embed، در قالب فوق مشاهده میکنید.
افزودن دکمهی چاپ PDF به برنامه
پس از اینکه به this.pdfBlobUrl دسترسی یافتیم، اکنون میتوان یک iframe مخفی را ایجاد کرد، سپس src آنرا به این آدرس ویژه تنظیم نمود و در آخر متد print آنرا فراخوانی کرد که سبب نمایش خودکار دیالوگ چاپ مرورگر میشود:
نمایش فایل PDF در یک برگهی جدید
اگر علاقمند بودید تا این فایل PDF را به صورت تمام صفحه و در برگهای جدید نمایش دهید، میتوان از متد window.open استفاده کرد:
دریافت فایل PDF
بجای نمایش فایل PDF میتوان دکمهای را بر روی صفحه قرار داد که با کلیک بر روی آن، این فایل توسط مرورگر به صورت متداولی جهت دریافت به کاربر ارائه شود:
در اینجا یک anchor جدید به صورت مخفی به صفحه اضافه میشود که href آن به this.pdfBlobUrl تنظیم شدهاست. سپس متد click آن فراخوانی خواهد شد. نام این فایل را هم توسط ویژگی download این شیء میتوان تنظیم نمود.
این روش در مورد تدارک دکمهی دریافت تمام blobهای دریافتی از سرور کاربرد دارد و منحصر به فایلهای PDF نیست.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید.
کدهای سمت سرور دریافت فایل PDF
در اینجا کدهای سمت سرور برنامه، نکتهی خاصی را به همراه نداشته و صرفا یک فایل PDF ساده (محتوای باینری) را بازگشت میدهد:
using Microsoft.AspNetCore.Mvc; namespace AngularTemplateDrivenFormsLab.Controllers { [Route("api/[controller]")] public class ReportsController : Controller { [HttpGet("[action]")] public IActionResult GetPdfReport() { return File(virtualPath: "~/assets/sample.pdf", contentType: "application/pdf", fileDownloadName: "sample.pdf"); } } }
سرویس دریافت محتوای باینری در برنامههای Angular
برای اینکه HttpClient برنامههای Angular بتواند محتوای باینری را بجای محتوای JSON پیشفرض آن دریافت کند، نیاز است نوع خروجی سمت سرور آنرا به blob تنظیم کرد:
import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Observable"; import { HttpClient } from "@angular/common/http"; @Injectable() export class DownloadPdfDataService { constructor(private httpClient: HttpClient) { } public getReport(): Observable<Blob> { return this.httpClient.get("/api/Reports/GetPdfReport", { responseType: "blob" }); } }
اصلاح Content Security Policy سمت سرور جهت ارائهی محتوای blob
پس از دریافت فایل PDF به صورت یک blob، با استفاده از متد URL.createObjectURL میتوان آدرس موقت محلی را برای دسترسی به آن تولید کرد و یک چنین آدرسهایی به صورت blob:http تولید میشوند. در این حالت در Content Security Policy سمت سرور، نیاز است امکان دسترسی به تصاویر و همچنین اشیاء از نوع blob را نیز آزاد معرفی کنید:
img-src 'self' data: blob: default-src 'self' blob: object-src 'self' blob:
دریافت فایلهای PDF از سرور و نمایش آنها در یک برنامهی Angular
پس از این مقدمات، کامپوننتی که یک فایل PDF را از سمت سرور دریافت کرده و نمایش میدهد، چنین کدی را خواهد داشت:
import { DownloadPdfDataService } from "./../download-pdf-data.service"; import { WindowRefService } from "./../../core/window.service"; import { Component, OnInit } from "@angular/core"; import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser"; @Component({ templateUrl: "./view-pdf.component.html", styleUrls: ["./view-pdf.component.css"] }) export class ViewPdfComponent implements OnInit { private nativeWindow: Window; private pdfBlobUrl: string; sanitizedPdfBlobResourceUrl: SafeResourceUrl; constructor(private downloadService: DownloadPdfDataService, private windowRefService: WindowRefService, private sanitizer: DomSanitizer) { } ngOnInit() { this.nativeWindow = this.windowRefService.nativeWindow; this.downloadService.getReport().subscribe(pdfDataBlob => { console.log("pdfDataBlob", pdfDataBlob); const urlCreator = this.nativeWindow.URL; this.pdfBlobUrl = urlCreator.createObjectURL(pdfDataBlob); console.log("pdfBlobUrl", this.pdfBlobUrl); this.sanitizedPdfBlobResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfBlobUrl); }); } }
<h1>Display PDF Files</h1> <div *ngIf="sanitizedPdfBlobResourceUrl"> <h4>using iframe</h4> <iframe width="100%" height="600" [attr.src]="sanitizedPdfBlobResourceUrl" type="application/pdf"></iframe> <h4>using object</h4> <object [attr.data]="sanitizedPdfBlobResourceUrl" type="application/pdf" width="100%" height="100%"></object> <h4>usin embed</h4> <embed [attr.src]="sanitizedPdfBlobResourceUrl" type="application/pdf" width="100%" height="100%"> </div>
- سپس مشترک متد getReport دریافت فایل PDF شده و اطلاعات نهایی آنرا به صورت pdfDataBlob دریافت میکنیم.
- این اطلاعات باینری را به متد createObjectURL ارسال کرده و آدرس موقتی این تصویر را در مرورگر بدست میآوریم.
- چون در این حالت Angular این URL را امن سازی میکند، یک چنین خروجی unsafe:blob بجای blob تولید خواهد شد که نمایش این مورد نیز توسط مرورگر سد میشود. برای رفع این مشکل، میتوان از سرویس DomSanitizer آن که به سازندهی کلاس تزریق شدهاست استفاده کرد:
this.sanitizedPdfBlobResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfBlobUrl);
اینبار یک چنین انتسابی به صورت مستقیم کار میکند که سه نمونهی این انتساب را به اشیاء iframe ،object و embed، در قالب فوق مشاهده میکنید.
افزودن دکمهی چاپ PDF به برنامه
پس از اینکه به this.pdfBlobUrl دسترسی یافتیم، اکنون میتوان یک iframe مخفی را ایجاد کرد، سپس src آنرا به این آدرس ویژه تنظیم نمود و در آخر متد print آنرا فراخوانی کرد که سبب نمایش خودکار دیالوگ چاپ مرورگر میشود:
printPdf() { const iframe = document.createElement("iframe"); iframe.style.display = "none"; iframe.src = this.pdfBlobUrl; document.body.appendChild(iframe); iframe.contentWindow.print(); }
نمایش فایل PDF در یک برگهی جدید
اگر علاقمند بودید تا این فایل PDF را به صورت تمام صفحه و در برگهای جدید نمایش دهید، میتوان از متد window.open استفاده کرد:
showPdf() { this.nativeWindow.open(this.pdfBlobUrl); }
دریافت فایل PDF
بجای نمایش فایل PDF میتوان دکمهای را بر روی صفحه قرار داد که با کلیک بر روی آن، این فایل توسط مرورگر به صورت متداولی جهت دریافت به کاربر ارائه شود:
downloadPdf() { const fileName = "test.pdf"; const anchor = document.createElement("a"); anchor.style.display = "none"; anchor.href = this.pdfBlobUrl; anchor.download = fileName; document.body.appendChild(anchor); anchor.click(); }
این روش در مورد تدارک دکمهی دریافت تمام blobهای دریافتی از سرور کاربرد دارد و منحصر به فایلهای PDF نیست.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید.
اشتراکها