我的專案中有一個表單,我在其中輸入用戶資料并使用這些資料生成 JSPDF 檔案,我需要將生成的 PDF 檔案發送到“報告”FormControl 以將其發送到 API,以便我可以將其存盤在資料庫中。
我有一個 blob 變數將攜帶 blob,當我提交表單時,我呼叫 exportHtmlToPDF() 函式將 div 轉換為 PDF 并將其作為 blob 輸出到 blob 變數
blob: any;
createUserForm: FormGroup = new FormGroup({
'name': new FormControl(null, [Validators.required, Validators.minLength(3), Validators.maxLength(100)]),
'gender': new FormControl(null, [Validators.required]),
'date_of_birth': new FormControl(null, [Validators.required]),
'identity': new FormControl(null, [Validators.required, Validators.minLength(9), Validators.maxLength(14)]),
'patient_id': new FormControl(null, [Validators.required, Validators.minLength(3), Validators.maxLength(100)]),
'test': new FormControl(null, [Validators.required, Validators.minLength(3), Validators.maxLength(100)]),
'result': new FormControl(null, [Validators.required]),
'collect_date': new FormControl(null, [Validators.required]),
'report_date': new FormControl(null, [Validators.required]),
'branch': new FormControl(null, [Validators.required, Validators.minLength(3), Validators.maxLength(100)]),
'reference_range': new FormControl(null, [Validators.required]),
'lab_director': new FormControl(null, [Validators.required, Validators.minLength(3), Validators.maxLength(100)]),
'qr_url': new FormControl(this.qrCode),
'qr_link': new FormControl(this.qrLink),
'report': new FormControl(null)
});
onSubmit() {
this.exportHtmlToPDF();
let formData = new FormData();
formData.append('name', this.createUserForm.get('name')?.value);
formData.append('gender', this.createUserForm.get('gender')?.value);
formData.append('date_of_birth', this.createUserForm.get('date_of_birth')?.value);
formData.append('identity', this.createUserForm.get('identity')?.value);
formData.append('patient_id', this.createUserForm.get('patient_id')?.value);
formData.append('test', this.createUserForm.get('test')?.value);
formData.append('result', this.createUserForm.get('result')?.value);
formData.append('collect_date', this.createUserForm.get('collect_date')?.value);
formData.append('report_date', this.createUserForm.get('report_date')?.value);
formData.append('branch', this.createUserForm.get('branch')?.value);
formData.append('reference_range', this.createUserForm.get('reference_range')?.value);
formData.append('lab_director', this.createUserForm.get('lab_director')?.value);
formData.append('qr_url', this.createUserForm.get('qr_url')?.value);
formData.append('qr_link', this.createUserForm.get('qr_link')?.value);
formData.append('report', this.blob);
this._UsersService.storeUser(formData).subscribe(data => {
if (data == "Customer Added Successfully") {
alert('customer added!')
}
});
}
public exportHtmlToPDF() {
let data = document.getElementById('pdf')!;
html2canvas(data).then(canvas => {
let docWidth = 208;
let docHeight = canvas.height * docWidth / canvas.width;
const contentDataURL = canvas.toDataURL('image/png');
let doc = new jsPDF('p', 'mm', 'a4');
let position = 0;
doc.addImage(contentDataURL, 'PNG', 0, position, docWidth, docHeight);
this.blob = doc.output('blob');
});
}
uj5u.com熱心網友回復:
我不想重復我自己,但是:不要toDataURL用于任何大于幾千位元組的東西:
- 生成
data:URI 很慢并且會阻塞瀏覽器的 UI/渲染執行緒(例如,當我將Blob包含 4K 壁紙大小的 JPEG 影像保存到 Base64data:URI 時,我在我強大的現代機器上的瀏覽器凍結了大約 5-7 秒,而使用URL.createObjectURL是即時的. - Base64 編碼將二進制資料的大小增加了 33%(因為它使用 4 個位元組的 ASCII 文本來表示 3 個原始二進制位元組)。
- 每次使用
data:URI 時,都必須對其進行驗證、決議、解碼,并將其內部二進制資料復制到新的目標緩沖區(瀏覽器內部)中。這是一大堆低效率。使用Blob完全避免了這種情況。 - 您不能使用
data:URI 直接上傳二進制資料,除非您的服務器端或后端邏輯經過專門編程來處理它(也沒有data:單獨代表URI 的官方 MIME 型別,并且舊的回退application/octet-stream也不合適),而如果您傳遞一個Blobtofetch或者XMLHttpRequest它也將使用正確的 MIME Con??tent-Type完美地上傳/傳輸二進制資料!
......順便說一下:
<canvas>支持將影像資料匯出為Blob物件,您可以將其直接傳遞到二進制上傳的FormData物件中multipart/form-data(就像<input type="file" />) - 以及請求正文的有效負載為原始資料的直接 PUT請求。Blob
顯然jsPDF的addImage函式HTMLCanvasElement直接接受a ,所以沒有必要使用toBlob(尤其不是toDataURL,eww)。
async function exportHtmlToPDF() {
const pdfElement = document.getElementById('pdf') as /* What element is it? */ | null;
if( !pdfElement ) throw new Error( "Couldn't find 'pdf' element." );
const canvas = await html2canvas( pdfElement );
let docWidth = 208;
let docHeight = canvas.height * docWidth / canvas.width;
const doc = new jsPDF( 'p', 'mm', 'a4' );
doc.addImage(canvas, 'PNG', /*x:*/ 0, /*y:*/ 0, docWidth, docHeight);
const pdfBlob = doc.output( 'blob' );
const uploadResponse = await fetch( '/pdf-upload-handler', { method: 'PUT', body: pdfBlob } );
console.log( uploadResponse );
}
但是我注意到您的程式實際上并不需要生成 PDF。您生成的 PDF 只是包裝了現有的 PNG 影像,那么為什么不上傳 PNG 影像并跳過(slooowwww)客戶端 PDF 生成呢?
async function exportHtmlToPng() {
const pdfElement = document.getElementById('pdf') as /* What element is it? */ | null;
if( !pdfElement ) throw new Error( "Couldn't find 'pdf' element." );
const canvas = await html2canvas( pdfElement );
canvas.toBlob( gotBlob, 'image/png' );
}
async function gotBlob( pngBlob: Blob | null ) {
if( !pngBlob ) return;
const uploadResponse = await fetch( '/png-image-upload-handler', { method: 'PUT', body: pngBlob } );
console.log( uploadResponse );
}
更好的是,這是一個帶有Promise配接器的版本toBlob:
async function exportHtmlToPng() {
const pdfElement = document.getElementById('pdf') as /* What element is it? */ | null;
if( !pdfElement ) throw new Error( "Couldn't find 'pdf' element." );
const canvas = await html2canvas( pdfElement );
const pngBlob = await getBlob( canvas, 'image/png' );
const uploadResponse = await fetch( '/png-image-upload-handler', { method: 'PUT', body: pngBlob } );
console.log( uploadResponse );
}
function getBlob( canvas: HTMLCanvasElement, type: string ): Promise<Blob> {
return new Promise( function( resolve, reject ) {
canvas.toBlob( function( blob ) => {
if( blob ) resolve( blob );
else reject( "Failed to create Blob from Canvas." );
}, type );
} );
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/379931.html
標籤:有角的
上一篇:元素隱式具有'any'型別,因為型別'AbstractControl'沒有索引簽名。你的意思是呼叫“get”?ngtsc(7052)
