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
OptimizedMemoryStreamzamiastMemoryStreamwhenever an in-memory document might exceed 2 GB –MemoryStreamrzuca wyjątek, gdy jego jednorazowa tablica bazowa osiągnie ten limit. - Zwolnij instancje
FileSpecification(oraz wszelkie strumienie otwarte ręcznie dla nich) –FileSpecificationimplementujeIDisposable. - Sprawdź
Document.HasEmbeddedFilesprzed iteracjąEmbeddedFiles, aby pominąć niepotrzebne wyliczanie w dokumentach bez załączników. - Ustaw
MimeTypeiAFRelationshipna każdymFileSpecification, aby downstream PDF konsumenci mogli poprawnie klasyfikować załączniki. - Użyj
EmbeddedFileCollection.FindByNamedo pojedynczego wyszukiwania po nazwie zamiast pisać ręczną pętlę.
Typowe problemy
| Problem | Przyczyna | Rozwiązanie |
|---|---|---|
OutOfMemoryException zapisuje duży dokument do strumienia | MemoryStream jest ograniczony do pojedynczej ~2 GB tablicy bazowej | Zapisz do OptimizedMemoryStream zamiast tego |
FileSpecification.GetData() zwraca pustą tablicę | Pozycja źródłowego strumienia nie została zresetowana przed utworzeniem FileSpecification | Ustaw wskaźnik strumienia na pozycję 0 (lub otwórz go ponownie) przed przekazaniem go do FileSpecification |
EmbeddedFiles.FindByName zwraca null | Nazwa 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 wpis | Wiele 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 / Metoda | Opis |
|---|---|
OptimizedMemoryStream | Rozszerzalny strumień w pamięci, który przekracza limit 2 GB MemoryStream |
OptimizedMemoryStream.Write | Zapisz bajty do bufora |
OptimizedMemoryStream.ToArray | Zwróć buforowane bajty jako tablicę bajtów |
FileSpecification | Osadzony deskryptor załącznika pliku, oparty na strumieniu lub danych bajtowych |
FileSpecification.GetData | Pobierz surowe bajty osadzonego pliku |
FileSpecification.Params | Metadane (rozmiar, suma kontrolna, daty) dla osadzonego pliku |
EmbeddedFileCollection | Zbiór załączników FileSpecification na Document |
EmbeddedFileCollection.FindByName | Wyszukaj załącznik po nazwie |
EmbeddedFileCollection.Delete | Usuń załącznik po nazwie |
Document.AddEmbeddedFile | Wygodna metoda osadzania pliku z surowych bajtów |
Document.EmbeddedFiles | Kolekcja osadzonych plików dokumentu |
Document.HasEmbeddedFiles | Czy dokument zawiera jakiekolwiek osadzone pliki |
FileParams | Opakowuje metadane rozmiaru, sumy kontrolnej i daty dla osadzonego strumienia plików |