Streams und Dateianhänge
Streams und Dateianhänge
Über die grundlegenden Document.Open/Document.Save-Überladungen hinaus bietet Aspose.PDF FOSS für .NET Ihnen eine feinere Kontrolle darüber, wie Bytes in ein Dokument hinein- und aus ihm herausfließen – erweiterbare In-Memory-Puffer für sehr große Dateien und ein dedizierter API zum Einbetten, Untersuchen und Extrahieren von Dateianhängen über FileSpecification und EmbeddedFileCollection.
Erweitern von In-Memory-Puffern über 2GB hinaus
MemoryStream speichert seine Daten in einem einzelnen zusammenhängenden Array, das bei etwa 2GB endet. OptimizedMemoryStream speichert Daten stattdessen in gleichgroßen Blöcken, sodass es viel größere Dokumente halten kann, wenn Sie ein PDF vollständig im Speicher speichern oder erstellen.
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}");Sie können auch direkt darauf schreiben, genau wie bei jedem 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);Einbetten einer Datei direkt aus einem Stream
FileSpecification kann ein Stream einbetten, anstatt zu verlangen, dass Sie den Anhang zuerst in ein byte[] puffern. Das ist nützlich, wenn die Quelle des Anhangs selbst ein Stream ist, etwa ein offener Dateihandle.
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");Einbetten einer Datei aus rohen Bytes
Document.AddEmbeddedFile ist eine Komfortmethode zum Einbetten einer Datei direkt aus einem Byte-Array, ohne ein FileSpecification direkt zu konstruieren.
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");Auflisten und Extrahieren eingebetteter Dateien
Document.EmbeddedFiles ist ein EmbeddedFileCollection, das Sie aufzählen können. Jeder Eintrag ist ein FileSpecification, und GetData() gibt die rohen Bytes des Anhangs zurück.
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);
}
}Finden, Inspizieren und Entfernen von Anhängen
Verwenden Sie FindByName, um einen einzelnen Anhang nachzuschlagen, Params, um seine Metadaten zu lesen, und Delete/DeleteByKey, um ihn zu entfernen.
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");Tipps und bewährte Vorgehensweisen
- Bevorzugen Sie
OptimizedMemoryStreamgegenüberMemoryStream, wann immer ein In-Memory-Dokument 2GB überschreiten könnte –MemoryStreamwirft eine Ausnahme, sobald sein einzelnes zugrunde liegendes Array dieses Limit erreicht. - Entsorgen Sie
FileSpecification-Instanzen (und jeden Stream, den Sie manuell dafür geöffnet haben) –FileSpecificationimplementiertIDisposable. - Prüfen Sie
Document.HasEmbeddedFilesbevor SieEmbeddedFilesiterieren, um unnötige Aufzählungen bei Dokumenten ohne Anhänge zu überspringen. - Setzen Sie
MimeTypeundAFRelationshipauf jedemFileSpecification, damit nachgelagerte PDF-Verbraucher Anhänge korrekt klassifizieren können. - Verwenden Sie
EmbeddedFileCollection.FindByNamefür eine einzelne benannte Suche, anstatt eine manuelle Schleife zu schreiben.
Häufige Probleme
| Problem | Ursache | Lösung |
|---|---|---|
OutOfMemoryException speichert ein großes Dokument in einen Stream | MemoryStream ist auf ein einzelnes ~2 GB Backing-Array beschränkt | Speichern Sie stattdessen in OptimizedMemoryStream |
FileSpecification.GetData() gibt ein leeres Array zurück | Die Position des Quellstreams wurde nicht zurückgesetzt, bevor FileSpecification erstellt wurde | Setzen Sie den Stream auf Position0 (oder öffnen Sie ihn erneut), bevor Sie ihn an FileSpecification übergeben. |
EmbeddedFiles.FindByName gibt null zurück | Der Anhangsname stimmt nicht exakt überein (Suche erfolgt nach Namen) | Iterieren Sie doc.EmbeddedFiles und vergleichen Sie die Werte von Name, oder prüfen Sie Keys |
| Das Löschen eines Anhangs entfernt den falschen Eintrag | Mehrere Anhänge haben denselben Namen | Verwenden Sie DeleteByKey mit dem genauen Schlüssel aus Keys für eine eindeutige Entfernung |
FAQ
Was ist der Unterschied zwischen MemoryStream und OptimizedMemoryStream?
MemoryStream speichert seine Bytes in einem zusammenhängenden Array, das bei etwa 2GB begrenzt ist. OptimizedMemoryStream speichert Daten stattdessen in Festgrößen-Blöcken, sodass es über diese Grenze hinaus wachsen kann – nützlich für Document.Save-Operationen, die vollständig im Speicher auf sehr großen Dateien durchgeführt werden.
Kann ich eine Datei einbetten, ohne sie zuerst in ein byte[] zu laden?
Ja. FileSpecification(stream, name, description) akzeptiert ein Stream direkt, sodass Sie aus File.OpenRead(...) oder jedem anderen Stream einbetten können, ohne es selbst in den Speicher zu puffern.
Wie bekomme ich eine eingebettete Datei aus einem Dokument zurück?
Durchlaufen Sie doc.EmbeddedFiles und rufen Sie GetData() für jedes FileSpecification auf, um die rohen Bytes zu erhalten.
Entfernt EmbeddedFileCollection.Delete(name) jeden Anhang mit diesem Namen?
Nein – richten Sie sich mit DeleteByKey präzise auf einen Anhang und den spezifischen Schlüssel aus Keys, falls mehrere Anhänge denselben Namen haben.
Ist FileSpecification sicher, um es in mehreren Dokumenten wiederzuverwenden?
Nein. FileSpecification implementiert IDisposable und kapselt einen einzelnen eingebetteten Dateistream; erstellen Sie für jeden Anhang in jedem Dokument eine neue Instanz.
API Reference Zusammenfassung
| Klasse / Methode | Beschreibung |
|---|---|
OptimizedMemoryStream | Wachsender In-Memory-Stream, der das 2GB-Limit von MemoryStream überschreitet |
OptimizedMemoryStream.Write | Bytes in den Puffer schreiben |
OptimizedMemoryStream.ToArray | Gib die gepufferten Bytes als Byte-Array zurück |
FileSpecification | Eingebetteter Dateianhang-Deskriptor, basierend auf einem Stream oder Byte-Daten |
FileSpecification.GetData | Rufen Sie die Rohbytes einer eingebetteten Datei ab |
FileSpecification.Params | Metadaten (Größe, Prüfsumme, Datumsangaben) für die eingebettete Datei |
EmbeddedFileCollection | Sammlung von FileSpecification-Anhängen auf einem Document |
EmbeddedFileCollection.FindByName | Einen Anhang nach Namen nachschlagen |
EmbeddedFileCollection.Delete | Entferne einen Anhang nach Namen |
Document.AddEmbeddedFile | Convenience-Methode zum Einbetten einer Datei aus rohen Bytes |
Document.EmbeddedFiles | Die Sammlung eingebetteter Dateien des Dokuments |
Document.HasEmbeddedFiles | Ob das Dokument eingebettete Dateien enthält |
FileParams | Kapselt Größen-/Prüfsummen-/Datums-Metadaten für einen eingebetteten Dateistream |