Luồng và Tệp Đính Kèm

Luồng và Tệp Đính Kèm

Luồng và Tệp Đính Kèm

Ngoài các bản tải trọng cơ bản Document.Open/Document.Save, Aspose.PDF FOSS cho .NET cung cấp cho bạn khả năng kiểm soát chi tiết hơn cách các byte di chuyển vào và ra tài liệu – các bộ đệm trong bộ nhớ có thể mở rộng cho các tệp rất lớn, và một API chuyên dụng để nhúng, kiểm tra và trích xuất các tệp đính kèm thông qua FileSpecification và EmbeddedFileCollection.


Mở rộng bộ đệm trong bộ nhớ vượt quá 2 GB

MemoryStream lưu trữ dữ liệu của nó trong một mảng liên tục duy nhất, giới hạn gần 2 GB. OptimizedMemoryStream lưu trữ dữ liệu thành các khối có kích thước cố định, vì vậy nó có thể chứa các tài liệu lớn hơn rất nhiều khi bạn lưu hoặc xây dựng PDF hoàn toàn trong bộ nhớ.

using Aspose.Pdf;

using var doc = Document.Open("large-input.pdf");
using var buffer = new OptimizedMemoryStream();

doc.Save(buffer);

buffer.Seek(0, SeekOrigin.Begin);
byte[] allBytes = buffer.ToArray();
Console.WriteLine($"Buffer length: {buffer.Length}");

Bạn cũng có thể ghi trực tiếp vào nó, giống như cách bạn làm với bất kỳ Stream nào:

using var buffer = new OptimizedMemoryStream();
byte[] chunk = System.Text.Encoding.UTF8.GetBytes("raw content chunk");

buffer.Write(chunk, 0, chunk.Length);
buffer.WriteByte(0x0A);
buffer.SetLength(buffer.Length);

Nhúng tệp trực tiếp từ một luồng

FileSpecification có thể bao bọc một Stream thay vì yêu cầu bạn phải lưu trữ tạm tệp đính kèm vào một byte[] trước. Điều này hữu ích khi nguồn tệp đính kèm tự nó là một luồng, chẳng hạn như một trình xử lý tệp mở.

using Aspose.Pdf;

using var doc = Document.Open("input.pdf");
using var attachmentStream = File.OpenRead("report.csv");
using var spec = new FileSpecification(attachmentStream, "report.csv", "Quarterly report data");

spec.MimeType = "text/csv";
spec.AFRelationship = AFRelationship.Data;
spec.Encoding = FileEncoding.Zip;

doc.EmbeddedFiles.Add(spec);
doc.Save("with-attachment.pdf");

Nhúng một tệp từ byte thô

Document.AddEmbeddedFile là một phương thức tiện lợi để nhúng tệp trực tiếp từ một mảng byte, mà không cần tạo một FileSpecification một cách trực tiếp.

using Aspose.Pdf;

using var doc = Document.Open("input.pdf");
byte[] fileData = File.ReadAllBytes("appendix.docx");

doc.AddEmbeddedFile(
    "appendix.docx",
    fileData,
    "Supporting appendix",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    true,
    DateTime.Now,
    DateTime.Now);

doc.Save("with-appendix.pdf");

Liệt kê và trích xuất các tệp được nhúng

Document.EmbeddedFiles là một EmbeddedFileCollection mà bạn có thể liệt kê. Mỗi mục là một FileSpecification, và GetData() trả về các byte thô của tệp đính kèm.

using Aspose.Pdf;

using var doc = Document.Open("with-attachment.pdf");

if (doc.HasEmbeddedFiles)
{
    foreach (FileSpecification file in doc.EmbeddedFiles)
    {
        Console.WriteLine($"{file.Name} ({file.Size} bytes, {file.MimeType})");
        byte[] contents = file.GetData();
        File.WriteAllBytes(file.Name, contents);
    }
}

Tìm kiếm, kiểm tra và xóa các tệp đính kèm

Sử dụng FindByName để tra cứu một tệp đính kèm duy nhất, Params để đọc siêu dữ liệu của nó, và Delete/DeleteByKey để xóa nó.

using Aspose.Pdf;

using var doc = Document.Open("with-attachment.pdf");

FileSpecification? found = doc.EmbeddedFiles.FindByName("report.csv");
if (found?.Params is FileParams info)
{
    Console.WriteLine($"{found.Name}: {info.Size} bytes, checksum {info.CheckSum}, modified {info.ModDate}");
}

doc.EmbeddedFiles.Delete("report.csv");
Console.WriteLine($"Remaining attachments: {doc.EmbeddedFiles.Count}");
doc.Save("cleaned.pdf");

Mẹo và Thực hành Tốt nhất

  • Ưu tiên OptimizedMemoryStream hơn MemoryStream bất cứ khi nào tài liệu trong bộ nhớ có thể vượt quá 2 GB — MemoryStream sẽ ném ngoại lệ khi mảng nền duy nhất của nó đạt tới giới hạn đó.
  • Giải phóng các đối tượng FileSpecification (và bất kỳ luồng nào bạn đã mở thủ công cho chúng) – FileSpecification thực thi IDisposable.
  • Kiểm tra Document.HasEmbeddedFiles trước khi lặp qua EmbeddedFiles để bỏ qua việc liệt kê không cần thiết trên các tài liệu không có tệp đính kèm.
  • Đặt MimeType và AFRelationship trên mỗi FileSpecification để các trình tiêu thụ PDF ở phía sau có thể phân loại tệp đính kèm một cách chính xác.
  • Sử dụng EmbeddedFileCollection.FindByName để tra cứu theo tên duy nhất thay vì viết một vòng lặp thủ công.

Các vấn đề thường gặp

Vấn đềNguyên nhânCách khắc phục
OutOfMemoryException lưu một tài liệu lớn vào luồngMemoryStream bị giới hạn ở một mảng nền duy nhất ~2 GBThay vào đó, lưu vào OptimizedMemoryStream
FileSpecification.GetData() trả về một mảng rỗngVị trí luồng nguồn chưa được đặt lại trước khi tạo FileSpecificationDi chuyển con trỏ luồng đến vị trí 0 (hoặc mở lại) trước khi truyền nó cho FileSpecification
EmbeddedFiles.FindByName trả về nullTên tệp đính kèm không khớp chính xác (tìm kiếm dựa trên tên)Lặp qua doc.EmbeddedFiles và so sánh các giá trị Name, hoặc kiểm tra Keys
Xóa một tệp đính kèm sẽ xóa mục saiNhiều tệp đính kèm có cùng tênSử dụng DeleteByKey với khóa chính xác từ Keys để xóa bỏ một cách không gây nhầm lẫn

FAQ

Sự khác biệt giữa MemoryStream và OptimizedMemoryStream là gì?

MemoryStream lưu trữ các byte của nó trong một mảng liên tục có giới hạn gần 2 GB. OptimizedMemoryStream lưu trữ dữ liệu thành các khối có kích thước cố định, vì vậy nó có thể mở rộng vượt qua giới hạn đó – hữu ích cho các thao tác Document.Save được thực hiện hoàn toàn trong bộ nhớ trên các tệp rất lớn.

Tôi có thể nhúng một tệp mà không cần tải nó vào một byte[] trước không?

Có. FileSpecification(stream, name, description) chấp nhận một Stream trực tiếp, vì vậy bạn có thể nhúng từ File.OpenRead(...) hoặc bất kỳ luồng nào khác mà không cần tự đệm nó vào bộ nhớ.

Làm sao tôi có thể lấy lại tệp đã nhúng từ tài liệu?

Duyệt doc.EmbeddedFiles và gọi GetData() trên mỗi FileSpecification để lấy các byte thô.

Liệu EmbeddedFileCollection.Delete(name) có xóa mọi tệp đính kèm có tên đó không?

Không — hãy nhắm chính xác một tệp đính kèm bằng DeleteByKey và khóa cụ thể từ Keys nếu có nhiều tệp đính kèm cùng tên.

Liệu FileSpecification có an toàn để tái sử dụng trên nhiều tài liệu không?

Không. FileSpecification triển khai IDisposable và bao bọc một luồng tệp đã nhúng duy nhất; hãy tạo một thể hiện mới cho mỗi tệp đính kèm trong mỗi tài liệu.


API Reference Tóm tắt

Lớp / Phương thứcMô tả
OptimizedMemoryStreamLuồng bộ nhớ trong có khả năng mở rộng vượt quá giới hạn 2 GB của MemoryStream
OptimizedMemoryStream.WriteGhi các byte vào bộ đệm
OptimizedMemoryStream.ToArrayTrả về các byte đã được đệm dưới dạng mảng byte
FileSpecificationMô tả tệp đính kèm nhúng, được hỗ trợ bởi một luồng hoặc dữ liệu byte
FileSpecification.GetDataLấy các byte thô của tệp nhúng
FileSpecification.ParamsSiêu dữ liệu (kích thước, checksum, ngày) cho tệp nhúng
EmbeddedFileCollectionBộ sưu tập các tệp đính kèm FileSpecification trên một Document
EmbeddedFileCollection.FindByNameTra cứu tệp đính kèm theo tên
EmbeddedFileCollection.DeleteXóa tệp đính kèm theo tên
Document.AddEmbeddedFilePhương thức tiện lợi để nhúng tệp từ dữ liệu thô
Document.EmbeddedFilesBộ sưu tập tệp nhúng của tài liệu
Document.HasEmbeddedFilesXác định xem tài liệu có chứa bất kỳ tệp nhúng nào hay không
FileParamsBao bọc siêu dữ liệu kích thước/mã kiểm tra/ngày cho luồng tệp được nhúng

Xem thêm

 Tiếng Việt