解决Kendo React PDF上传Firebase Storage的CORS及调用问题
Great question! I’ve dealt with exactly these issues when integrating Kendo React’s PDF tools with Firebase Storage, so let’s break down the problems and fix them one by one.
Core Issue: Get a PDF Blob Instead of Direct Download
The key to uploading is to retrieve the PDF as a Blob object (not trigger an immediate download). Both drawingDOM() and the PDFExport component can be adjusted to do this—let’s cover both approaches, plus fix the CORS problem.
1. Fixing CORS Issues with drawingDOM()
The CORS error happens because when drawingDOM() renders images, browsers block cross-origin image data from being used in Canvas (which Kendo uses under the hood to generate PDFs). Here’s how to fix it:
Step 1: Configure Image Sources for CORS
- For any
<img>tags in your PDF content, add thecrossOrigin="anonymous"attribute:<img src="https://your-cross-origin-image-url.com/image.jpg" crossOrigin="anonymous" /> - If you’re using Kendo components (like Grid with image columns), make sure the rendered
<img>elements include this attribute. You can customize the column template to add it:<GridColumn field="imageUrl" title="Image"> {(props) => <img src={props.dataItem.imageUrl} crossOrigin="anonymous" />} </GridColumn>
Step 2: Configure Your Image Host’s CORS Rules
- If your images are hosted on Firebase Storage, you’ll need to set up a CORS configuration file for your bucket. Create a
cors.jsonfile with this content:[ { "origin": ["http://localhost:3000", "https://your-production-domain.com"], "method": ["GET"], "maxAgeSeconds": 3600 } ] - Upload it using the Firebase CLI:
gsutil cors set cors.json gs://your-firebase-storage-bucket-url - For other hosts (like Cloudinary, AWS S3), follow their documentation to enable CORS for your domain.
2. Generate PDF Blob & Upload to Firebase
Once CORS is fixed, you can use drawingDOM() to generate a PDF Blob and upload it directly:
import { drawing, pdf } from '@progress/kendo-drawing'; import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage"; async function generateAndUploadPDF() { // Get the DOM element you want to convert to PDF const pdfContent = document.getElementById('pdf-content-container'); try { // Render the DOM to a Kendo Drawing element const drawingElement = await drawing.drawDOM(pdfContent, { // Optional: Configure rendering options (size, margins, etc.) paperSize: 'A4', margin: '2cm' }); // Export the drawing to PDF data (Uint8Array) const pdfData = await pdf.exportPDF(drawingElement); // Convert to a Blob object const pdfBlob = new Blob([pdfData], { type: 'application/pdf' }); // Upload to Firebase Storage const storage = getStorage(); const storageRef = ref(storage, `pdfs/${Date.now()}-document.pdf`); // Unique filename // Start upload const uploadSnapshot = await uploadBytes(storageRef, pdfBlob); // Get the download URL (optional) const downloadURL = await getDownloadURL(uploadSnapshot.ref); console.log('PDF uploaded successfully! URL:', downloadURL); } catch (error) { console.error('Error generating/uploading PDF:', error); } }
3. Using PDFExport Component (No Direct Download)
If you prefer using Kendo’s PDFExport component, you can disable the automatic download and grab the PDF data instead:
import { PDFExport } from '@progress/kendo-react-pdf'; import { useRef } from 'react'; import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage"; function PDFUploadComponent() { const pdfExportRef = useRef(null); const handleExportAndUpload = async () => { if (!pdfExportRef.current) return; // Export the content to PDF data (Uint8Array) const pdfData = await pdfExportRef.current.export(); // Convert to Blob const pdfBlob = new Blob([pdfData], { type: 'application/pdf' }); // Upload to Firebase (same as above) const storage = getStorage(); const storageRef = ref(storage, `pdfs/${Date.now()}-exported.pdf`); try { const uploadSnapshot = await uploadBytes(storageRef, pdfBlob); const downloadURL = await getDownloadURL(uploadSnapshot.ref); console.log('Upload complete! PDF URL:', downloadURL); } catch (error) { console.error('Upload failed:', error); } }; return ( <div> <button onClick={handleExportAndUpload}>Export & Upload PDF</button> {/* Disable automatic download with saveFile={false} */} <PDFExport ref={pdfExportRef} saveFile={false} paperSize="A4"> {/* Your PDF content goes here */} <div id="pdf-content-container"> <h1>My Custom PDF</h1> <img src="https://your-image-url.com/image.jpg" crossOrigin="anonymous" /> </div> </PDFExport> </div> ); }
Key Notes
- Always test CORS fixes first: If you still get errors, check your browser’s network tab to ensure the image request includes the
Originheader and the server responds withAccess-Control-Allow-Origin. - For local development, add
http://localhost:3000(or your dev port) to your CORS allowed origins. - Use unique filenames (like
Date.now()) to avoid overwriting existing files in Firebase Storage.
内容的提问来源于stack exchange,提问作者user2521295

