Strumienie i załączniki plików

Strumienie i załączniki plików

Strumienie i załączniki plików

Poza podstawowymi przeciążeniami Document.Open/Document.Save, Aspose.PDF FOSS dla .NET daje Ci bardziej precyzyjną kontrolę nad tym, jak bajty przemieszczają się w dokumencie i z niego – rozrastające się buforu w pamięci dla bardzo dużych plików oraz dedykowany API do osadzania, przeglądania i wyodrębniania załączników plików za pomocą FileSpecification i EmbeddedFileCollection.


Rozrastanie buforów w pamięci powyżej 2GB

MemoryStream przechowuje swoje dane w jednej ciągłej tablicy, której limit wynosi około 2GB. OptimizedMemoryStream przechowuje dane w stałych fragmentach, dzięki czemu może pomieścić znacznie większe dokumenty, gdy zapisujesz lub budujesz PDF całkowicie w pamięci.

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}");

Możesz także zapisywać do niego bezpośrednio, tak jak z dowolnym Stream:

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);

Osadzanie pliku bezpośrednio ze strumienia

FileSpecification może opakować Stream zamiast wymagać najpierw buforowania załącznika w byte[]. Jest to przydatne, gdy źródło załącznika jest samym strumieniem, np. otwartym uchwytem pliku.

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");

Osadzanie pliku z surowych bajtów

Document.AddEmbeddedFile jest metodą ułatwiającą osadzanie pliku bezpośrednio z tablicy bajtów, bez bezpośredniego tworzenia FileSpecification.

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");

Enumerowanie i wyodrębnianie osadzonych plików

Document.EmbeddedFiles jest EmbeddedFileCollection, które możesz wyliczyć. Każdy wpis to FileSpecification, a GetData() zwraca surowe bajty załącznika.

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);
    }
}

Wyszukiwanie, przeglądanie i usuwanie załączników

Użyj FindByName, aby wyszukać pojedynczy załącznik, Params, aby odczytać jego metadane, oraz Delete/DeleteByKey, aby go usunąć.

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");

Wskazówki i najlepsze praktyki

  • Preferuj OptimizedMemoryStream zamiast MemoryStream whenever an in-memory document might exceed 2 GB – MemoryStream rzuca wyjątek, gdy jego jednorazowa tablica bazowa osiągnie ten limit.
  • Zwolnij instancje FileSpecification (oraz wszelkie strumienie otwarte ręcznie dla nich) – FileSpecification implementuje IDisposable.
  • Sprawdź Document.HasEmbeddedFiles przed iteracją EmbeddedFiles, aby pominąć niepotrzebne wyliczanie w dokumentach bez załączników.
  • Ustaw MimeType i AFRelationship na każdym FileSpecification, aby downstream PDF konsumenci mogli poprawnie klasyfikować załączniki.
  • Użyj EmbeddedFileCollection.FindByName do pojedynczego wyszukiwania po nazwie zamiast pisać ręczną pętlę.

Typowe problemy

ProblemPrzyczynaRozwiązanie
OutOfMemoryException zapisuje duży dokument do strumieniaMemoryStream jest ograniczony do pojedynczej ~2 GB tablicy bazowejZapisz do OptimizedMemoryStream zamiast tego
FileSpecification.GetData() zwraca pustą tablicęPozycja źródłowego strumienia nie została zresetowana przed utworzeniem FileSpecificationUstaw wskaźnik strumienia na pozycję 0 (lub otwórz go ponownie) przed przekazaniem go do FileSpecification
EmbeddedFiles.FindByName zwraca nullNazwa załącznika nie pasuje dokładnie (wyszukiwanie jest oparte na nazwie)Iteruj doc.EmbeddedFiles i porównaj wartości Name, lub sprawdź Keys
Usunięcie załącznika usuwa niewłaściwy wpisWiele załączników ma tę samą nazwęUżyj DeleteByKey z dokładnym kluczem z Keys do jednoznacznego usunięcia

FAQ

Jaka jest różnica między MemoryStream a OptimizedMemoryStream?

MemoryStream przechowuje swoje bajty w jednej ciągłej tablicy ograniczonej do około 2GB. OptimizedMemoryStream przechowuje dane w stałych fragmentach, dzięki czemu może przekraczać ten limit – przydatne dla operacji Document.Save wykonywanych w całości w pamięci na bardzo dużych plikach.

Czy mogę osadzić plik bez najpierw ładowania go do byte[]?

Tak. FileSpecification(stream, name, description) akceptuje Stream bezpośrednio, więc możesz osadzić z File.OpenRead(...) lub dowolnego innego strumienia, bez buforowania go w pamięci samodzielnie.

Jak wyciągnąć osadzony plik z dokumentu?

Iteruj doc.EmbeddedFiles i wywołaj GetData() na każdym FileSpecification, aby pobrać surowe bajty.

Czy EmbeddedFileCollection.Delete(name) usuwa każdy załącznik o tej nazwie?

Nie — celuj dokładnie w jeden załącznik przy użyciu DeleteByKey oraz konkretnego klucza z Keys, jeśli wiele załączników ma tę samą nazwę.

Czy FileSpecification jest bezpieczny do ponownego użycia w wielu dokumentach?

Nie. FileSpecification implementuje IDisposable i opakowuje pojedynczy strumień osadzonego pliku; utwórz nową instancję dla każdego załącznika w każdym dokumencie.


API Reference Podsumowanie

Klasa / MetodaOpis
OptimizedMemoryStreamRozszerzalny strumień w pamięci, który przekracza limit 2 GB MemoryStream
OptimizedMemoryStream.WriteZapisz bajty do bufora
OptimizedMemoryStream.ToArrayZwróć buforowane bajty jako tablicę bajtów
FileSpecificationOsadzony deskryptor załącznika pliku, oparty na strumieniu lub danych bajtowych
FileSpecification.GetDataPobierz surowe bajty osadzonego pliku
FileSpecification.ParamsMetadane (rozmiar, suma kontrolna, daty) dla osadzonego pliku
EmbeddedFileCollectionZbiór załączników FileSpecification na Document
EmbeddedFileCollection.FindByNameWyszukaj załącznik po nazwie
EmbeddedFileCollection.DeleteUsuń załącznik po nazwie
Document.AddEmbeddedFileWygodna metoda osadzania pliku z surowych bajtów
Document.EmbeddedFilesKolekcja osadzonych plików dokumentu
Document.HasEmbeddedFilesCzy dokument zawiera jakiekolwiek osadzone pliki
FileParamsOpakowuje metadane rozmiaru, sumy kontrolnej i daty dla osadzonego strumienia plików

Zobacz także

 Polski