Analyzing your prompt, please hold on...
An error occurred while retrieving the results. Please refresh the page and try again.
Jika Anda membangun aplikasi cloud-native di AWS dan memerlukan kemampuan generasi, manipulasi, atau konversi PDF yang kuat, mengintegrasikan Aspose.PDF for .NET ke dalam fungsi AWS Lambda menawarkan solusi yang kuat dan dapat diskalakan. Pendekatan ini memungkinkan Anda memanfaatkan fitur luas dari Aspose.PDF dalam lingkungan tanpa server AWS, yang berpotensi terintegrasi dengan layanan lain seperti S3 untuk penyimpanan.
Artikel ini membimbing Anda melalui pengaturan dan menjalankan Aspose.PDF for .NET di AWS Lambda, mencakup pembuatan PDF dasar dan mengatasi tantangan umum seperti manajemen font di cloud.
Ikuti langkah-langkah ini untuk membuat fungsi Lambda sederhana yang menghasilkan dokumen PDF menggunakan Aspose.PDF dan menyimpannya ke Amazon S3:
Aspose.PDF
. Perpustakaan inti untuk manipulasi PDF.AWSSDK.S3
. Perpustakaan AWS SDK untuk .NET untuk berinteraksi dengan penyimpanan S3.Function.cs
) dengan kode berikut. Contoh ini membuat dokumen PDF dasar dengan teks dan menyimpannya ke bucket S3.using System;
using System.IO;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;
using Aspose.Pdf;
using Aspose.Pdf.Text;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace TestAsposePdfLambda
{
public class Function
{
private IAmazonS3 S3Client { get; set; }
private const string BucketName = "your-s3-bucket-name";
/// <summary>
/// Default constructor. Initializes the S3 client.
/// </summary>
public Function()
{
S3Client = new AmazonS3Client();
// Consider setting the License here if needed, e.g., in a static constructor
Aspose.Pdf.License lic = new Aspose.Pdf.License();
// Assumes license file is an embedded resource
lic.SetLicense("Aspose.PDF.lic");
}
/// <summary>
/// Lambda function handler: Creates a PDF document and saves it to S3.
/// </summary>
public async Task<string> FunctionHandler(string input, ILambdaContext context)
{
context.Logger.LogLine($"Function processing input: {input}");
// Create PDF document
Document pdfDocument = new Document();
// Add a page
Page page = pdfDocument.Pages.Add();
// Add text elements
page.Paragraphs.Add(new TextFragment($"Hello {input} from Aspose.PDF!"));
page.Paragraphs.Add(new TextFragment($"You are running on: {System.Environment.OSVersion.VersionString}"));
// Save the PDF to a MemoryStream
using (MemoryStream ms = new MemoryStream())
{
// Aspose.PDF saves directly to PDF format
pdfDocument.Save(ms);
// Reset stream position for reading
ms.Position = 0;
// Upload the stream to S3
string outputKey = $"AP_out_{DateTime.UtcNow:yyyyMMddHHmmss}.pdf";
context.Logger.LogLine($"Attempting to upload {outputKey} to bucket {BucketName}");
bool putResult = await PutS3Object(BucketName, outputKey, ms, context);
return putResult ? $"OK - PDF saved as s3://{BucketName}/{outputKey}" : "FAILED to upload PDF to S3";
}
}
/// <summary>
/// Helper method to upload a stream to an S3 bucket.
/// </summary>
private async Task<bool> PutS3Object(string bucket, string key, Stream content, ILambdaContext context)
{
try
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucket,
Key = key,
InputStream = content,
// Set appropriate content type
ContentType = "application/pdf"
};
var response = await S3Client.PutObjectAsync(request);
context.Logger.LogLine($"S3 PutObject Response: {response.HttpStatusCode}");
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
catch (AmazonS3Exception s3ex)
{
context.Logger.LogLine($"Error uploading to S3: {s3ex.Message} (AWS Request ID: {s3ex.RequestId}, Error Code: {s3ex.ErrorCode})");
return false;
}
catch (Exception ex)
{
context.Logger.LogLine($"General error during S3 upload: {ex.Message}");
return false;
}
}
}
}
"your-s3-bucket-name"
dalam kode dengan nama bucket S3 yang Anda miliki akses tulis.AP_out_... .pdf
).Ketika Anda memeriksa PDF yang dihasilkan, Anda mungkin memperhatikan bahwa teks tidak menggunakan font standar yang Anda harapkan (seperti Arial atau Times New Roman). Sebaliknya, Aspose.PDF mungkin menggunakan font cadangan. Lingkungan eksekusi AWS Lambda adalah kontainer Linux minimal. Mereka biasanya tidak memiliki font TrueType umum yang ditemukan di Windows atau distribusi Linux desktop. Ketika Aspose.PDF tidak dapat menemukan font yang ditentukan atau default, ia menggantinya dengan font cadangan yang tersedia untuk memastikan teks tetap dirender. Ini dapat mempengaruhi kesetiaan visual dokumen Anda.
Untuk memastikan PDF Anda dirender dengan font yang benar, Anda perlu menyediakannya untuk Aspose.PDF dalam lingkungan Lambda. Menyimpan font di bucket S3 adalah pendekatan yang fleksibel dan umum untuk aplikasi cloud:
Fonts
) di bucket S3 Anda dan unggah file font TrueType (.ttf
) atau OpenType (.otf
) yang diperlukan. Untuk demonstrasi, Anda bisa menggunakan set yang tersedia secara gratis seperti “Noto Sans”.FontRepository
Aspose.PDF.Berikut cara Anda dapat menyesuaikan kode fungsi Lambda sebelumnya:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;
using Aspose.Pdf;
using Aspose.Pdf.Text;
// Assembly attribute
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace TestAsposePdfLambda
{
public class Function
{
private IAmazonS3 S3Client { get; set; }
private const string BucketName = "your-s3-bucket-name"; // Replace with your bucket name
private const string FontsS3Folder = "Fonts/"; // Folder in your bucket containing .ttf/.otf files
private static bool _fontsLoaded = false; // Flag to load fonts only once per container instance
private static readonly object _fontLoadLock = new object(); // Lock for thread safety
/// <summary>
/// Static constructor: Ensures fonts are loaded when the class is first accessed
/// within a Lambda execution environment instance.
/// </summary>
static Function()
{
// Consider setting the License here if needed
Aspose.Pdf.License lic = new Aspose.Pdf.License();
lic.SetLicense("Aspose.PDF.lic");
}
/// <summary>
/// Default constructor. Initializes S3 client.
/// </summary>
public Function()
{
S3Client = new AmazonS3Client();
// Ensure fonts are loaded
EnsureFontsLoaded(S3Client, BucketName, FontsS3Folder);
}
/// <summary>
/// Lambda function handler: Creates a PDF with custom fonts loaded from S3.
/// </summary>
public async Task<string> FunctionHandler(string input, ILambdaContext context)
{
context.Logger.LogLine($"Function processing input: {input}");
// Ensure fonts loaded (important for warm starts)
EnsureFontsLoaded(S3Client, BucketName, FontsS3Folder, context);
// Create PDF document
Document pdfDocument = new Document();
// Add a page
Page page = pdfDocument.Pages.Add();
// Create TextFragment and specify the font
TextFragment titleFragment = new TextFragment($"Hello {input} from Aspose.PDF!");
// Attempt to find the font loaded from S3. Use the actual font name
titleFragment.TextState.Font = FontRepository.FindFont("Noto Sans");
// If the font wasn't found/loaded, FindFont might return a default/fallback font
titleFragment.TextState.FontSize = 14;
page.Paragraphs.Add(titleFragment);
TextFragment infoFragment = new TextFragment($"Running on: {System.Environment.OSVersion.VersionString}");
// Example using a specific style
infoFragment.TextState.Font = FontRepository.FindFont("Noto Sans Regular");
infoFragment.TextState.FontSize = 10;
page.Paragraphs.Add(infoFragment);
// Save PDF to stream
using (MemoryStream ms = new MemoryStream())
{
pdfDocument.Save(ms);
ms.Position = 0;
// Upload to S3
string outputKey = $"AP_Font_out_{DateTime.UtcNow:yyyyMMddHHmmss}.pdf";
context.Logger.LogLine($"Attempting to upload {outputKey} to bucket {BucketName}");
bool putResult = await PutS3Object(BucketName, outputKey, ms, context);
return putResult ? $"OK - PDF saved as s3://{BucketName}/{outputKey}" : "FAILED to upload PDF to S3";
}
}
/// <summary>
/// Loads fonts from S3 into Aspose.PDF's FontRepository if not already loaded.
/// </summary>
private void EnsureFontsLoaded(IAmazonS3 s3Client, string bucketName, string fontsFolderKey, ILambdaContext context = null)
{
// Prevent multiple threads/invocations trying to load simultaneously
lock (_fontLoadLock)
{
if (_fontsLoaded)
{
return;
}
context?.Logger.LogLine("Attempting to load fonts from S3...");
try
{
// Get font sources from S3
var fontSources = Task.Run(async () => await GetS3FontSources(s3Client, bucketName, fontsFolderKey, context)).Result;
if (fontSources.Any())
{
// Clear existing default sources (optional, ensures only S3 fonts are primary)
// FontRepository.Sources.Clear();
// Add the sources loaded from S3
FontRepository.Sources.AddRange(fontSources);
context?.Logger.LogLine($"Successfully loaded {fontSources.Count()} font sources from S3.");
_fontsLoaded = true;
}
else
{
context?.Logger.LogLine("No font sources found in S3 folder.");
// Set _fontsLoaded to true anyway to avoid retrying every invocation if folder is empty/missing
_fontsLoaded = true;
}
}
catch (AggregateException aggEx) when (aggEx.InnerException is AmazonS3Exception s3Ex)
{
context?.Logger.LogLine($"S3 Error loading fonts: {s3Ex.Message} (Request ID: {s3Ex.RequestId}, Error Code: {s3Ex.ErrorCode}) - Check bucket/folder name and permissions.");
// Avoid retrying constantly on permission errors
_fontsLoaded = true;
}
catch (Exception ex)
{
context?.Logger.LogLine($"Error loading fonts from S3: {ex.ToString()}");
// Decide if you want to retry or not. Setting _fontsLoaded = true prevents retries.
_fontsLoaded = true;
}
}
}
/// <summary>
/// Lists font files in an S3 folder and creates MemoryFontSource for each.
/// </summary>
private static async Task<List<MemoryFontSource>> GetS3FontSources(IAmazonS3 client, string bucketName, string fontsFolderKey, ILambdaContext context)
{
List<MemoryFontSource> fontSources = new List<MemoryFontSource>();
ListObjectsV2Request request = new ListObjectsV2Request()
{
BucketName = bucketName,
// e.g., "Fonts/"
Prefix = fontsFolderKey,
};
context?.Logger.LogLine($"Listing objects in {bucketName}/{fontsFolderKey}");
ListObjectsV2Response response;
do
{
// Requires s3:ListBucket permission on the bucket
response = await client.ListObjectsV2Async(request);
foreach (S3Object entry in response.S3Objects)
{
// Skip the folder itself and non-font files (simple check)
if (entry.Key.EndsWith("/") || !(entry.Key.EndsWith(".ttf", StringComparison.OrdinalIgnoreCase) || entry.Key.EndsWith(".otf", StringComparison.OrdinalIgnoreCase)))
{
continue;
}
context?.Logger.LogLine($"Found font file: {entry.Key}");
try
{
// Requires s3:GetObject permission on the font files
GetObjectRequest fontRequest = new GetObjectRequest
{
BucketName = bucketName,
Key = entry.Key
};
using (GetObjectResponse fontResponse = await client.GetObjectAsync(fontRequest))
{
using (MemoryStream ms = new MemoryStream())
{
await fontResponse.ResponseStream.CopyToAsync(ms);
// IMPORTANT: Aspose.PDF needs the raw byte array for MemoryFontSource.
// It manages the stream internally after this.
fontSources.Add(new MemoryFontSource(ms.ToArray()));
context?.Logger.LogLine($" -- Added MemoryFontSource for {entry.Key}");
}
}
}
catch (Exception ex)
{
context?.Logger.LogLine($" -- Failed to load font {entry.Key}: {ex.Message}");
// Decide how to handle failures - continue or stop?
}
}
request.ContinuationToken = response.NextContinuationToken;
} while (response.IsTruncated);
return fontSources;
}
/// <summary>
/// Helper method to upload a stream to an S3 bucket.
/// </summary>
private async Task<bool> PutS3Object(string bucket, string key, Stream content, ILambdaContext context)
{
try
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucket,
Key = key,
InputStream = content,
// Set appropriate content type
ContentType = "application/pdf"
};
var response = await S3Client.PutObjectAsync(request);
context.Logger.LogLine($"S3 PutObject Response: {response.HttpStatusCode}");
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
catch (AmazonS3Exception s3ex)
{
context.Logger.LogLine($"Error uploading to S3: {s3ex.Message} (AWS Request ID: {s3ex.RequestId}, Error Code: {s3ex.ErrorCode})");
return false;
}
catch (Exception ex)
{
context.Logger.LogLine($"General error during S3 upload: {ex.Message}");
return false;
}
}
}
}
Analyzing your prompt, please hold on...
An error occurred while retrieving the results. Please refresh the page and try again.