To automatically upload the generated PDF to Google Drive when it’s generated, you need to:
- Programmatically Generate the PDF within your Blazor desktop app, so you have control over the creation process.
- Upload the PDF to Google Drive using the Google Drive API.
Since relying on the browser’s print function doesn’t give you control over the PDF generation process, generating the PDF programmatically allows you to know exactly when it’s created, enabling you to upload it immediately.
To generate a PDF from your HTML content within your Blazor app, you can use a .NET library that converts HTML to PDF. Some popular libraries include:
- DinkToPdf (A .NET Core wrapper for the
wkhtmltopdf library)
- SelectPdf
- IronPDF
- iTextSharp (iText7)
For this example, we’ll use DinkToPdf, which is free and open-source.
Add the NuGet package to your project:
Install-Package DinkToPdf
Install-Package DinkToPdf.Native.Win64
Note: Also install DinkToPdf.Native.Win64 or the appropriate native package for your platform.
using DinkToPdf.Contracts;
private void GeneratePdf(string htmlContent, string outputFilePath)
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument()
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
HtmlContent = htmlContent,
// Optionally include headers, footers, or other settings
Replace your existing OpenPreviewPage method with one that generates the PDF and then uploads it:
private async Task GenerateAndUploadPdf()
// Generate the HTML content
var htmlContent = await JS.InvokeAsync<string>("generatePrintClone");
var tempPdfPath = Path.Combine(Path.GetTempPath(), "Invoice.pdf");
GeneratePdf(htmlContent, tempPdfPath);
// Upload the PDF to Google Drive
await UploadPdfToGoogleDrive(tempPdfPath);
To upload files to Google Drive, you need to use the Google Drive API.
-
Create a Google Cloud Project:
-
Enable the Google Drive API:
- In the API Library, search for “Google Drive API” and enable it.
-
Set Up OAuth Consent Screen:
- Configure the consent screen, add scopes, and provide application details.
-
Create OAuth Credentials:
- Go to “Credentials” and create OAuth 2.0 Client ID credentials.
- Choose “Desktop App” as the application type.
- Download the
credentials.json file and place it in your project directory.
Install the NuGet package:
Install-Package Google.Apis.Drive.v3
Install-Package Google.Apis.Oauth2.v2
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services;
using Google.Apis.Util.Store;
private async Task UploadPdfToGoogleDrive(string pdfFilePath)
UserCredential credential;
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
// The file token.json stores the user's access and refresh tokens and is created automatically
string credPath = "token.json";
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { DriveService.Scope.DriveFile },
new FileDataStore(credPath, true));
// Create Drive API service.
var service = new DriveService(new BaseClientService.Initializer()
HttpClientInitializer = credential,
ApplicationName = "Your Application Name",
// Define parameters of request.
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
Name = Path.GetFileName(pdfFilePath),
FilesResource.CreateMediaUpload request;
using (var stream = new FileStream(pdfFilePath, FileMode.Open))
request = service.Files.Create(
fileMetadata, stream, "application/pdf");
await request.UploadAsync();
var file = request.ResponseBody;
Console.WriteLine("File ID: " + file.Id);
Combine the PDF generation and upload process:
private async Task GenerateAndUploadPdf()
// 1. Generate the HTML content
var htmlContent = await JS.InvokeAsync<string>("generatePrintClone");
var tempPdfPath = Path.Combine(Path.GetTempPath(), "Invoice.pdf");
GeneratePdf(htmlContent, tempPdfPath);
// 3. Upload the PDF to Google Drive
await UploadPdfToGoogleDrive(tempPdfPath);
// 4. Optionally, delete the temp PDF
if (File.Exists(tempPdfPath))
File.Delete(tempPdfPath);
Call GenerateAndUploadPdf() when you need to generate the PDF and upload it.
- User Consent: The first time the application runs, it will prompt the user to grant permission to access their Google Drive.
- Token Storage: The
token.json file stores the access and refresh tokens. Store this securely and consider its lifecycle.
Add try-catch blocks to handle exceptions during PDF generation and uploading.
Ensure that the PDF file name is appropriately set, possibly using the invoice reference and date as you did for the HTML title.
var invoiceReference = GetInvoiceReference(); // Implement this to retrieve your invoice reference
var currentDate = DateTime.Now.ToString("yyyy-MM-dd");
var pdfFileName = $"{currentDate} - {invoiceReference}.pdf";
var tempPdfPath = Path.Combine(Path.GetTempPath(), pdfFileName);
If you want to upload the PDF to a specific folder in Google Drive, you can modify the fileMetadata:
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
Name = Path.GetFileName(pdfFilePath),
Parents = new List<string> { "FolderID" } // Replace "FolderID" with the ID of the target folder
- Use the minimal required scopes for your application.
- For broader access, you may need to use
DriveService.Scope.Drive.
Set ApplicationName in the DriveService initializer to your application’s name.
Implement a method to get the invoice reference from your Blazor component:
private async Task<string> GetInvoiceReference()
// Assuming you have an element with ID 'invoice_reference' in your HTML
return await JS.InvokeAsync<string>("document.getElementById", "invoice_reference").GetProperty("value");
- Generate the PDF Programmatically: Use
DinkToPdf to convert your HTML content to a PDF file.
- Upload to Google Drive: Utilize the Google Drive API to upload the generated PDF.
- Know When the PDF is Generated: Since you control the generation process, you can trigger the upload immediately after.
- Automate the Process: Integrate both steps into your application’s workflow for seamless operation.
If you have questions about setting up the Google API credentials, handling authentication, or any other aspect of this solution, feel free to ask!