Flussi e allegati di file
Flussi e allegati di file
Oltre ai sovraccarichi di base Document.Open/Document.Save, Aspose.PDF FOSS per .NET ti offre un controllo più fine su come i byte si muovono dentro e fuori un documento – buffer in-memoria espandibili per file molto grandi, e un API dedicato per incorporare, ispezionare ed estrarre gli allegati di file tramite FileSpecification e EmbeddedFileCollection.
Espansione dei buffer in-memoria oltre 2GB
MemoryStream memorizza i suoi dati in un unico array contiguo, che si limita a circa 2GB. OptimizedMemoryStream memorizza i dati in blocchi di dimensione fissa, così può contenere documenti molto più grandi quando salvi o crei un PDF interamente in memoria.
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}");Puoi anche scrivere direttamente su di esso, allo stesso modo in cui faresti con qualsiasi 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);Incorporare un file direttamente da un flusso
FileSpecification può avvolgere un Stream invece di richiedere di bufferizzare l’allegato in un byte[] prima. Questo è utile quando la sorgente dell’allegato è a sua volta un flusso, ad esempio un handle di file aperto.
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");Incorporare un file da byte grezzi
Document.AddEmbeddedFile è un metodo di comodo per incorporare un file direttamente da un array di byte, senza creare un FileSpecification direttamente.
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");Enumerare ed estrarre file incorporati
Document.EmbeddedFiles è un EmbeddedFileCollection che puoi enumerare. Ogni voce è un FileSpecification, e GetData() restituisce i byte grezzi dell’allegato.
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);
}
}Trovare, ispezionare e rimuovere gli allegati
Usa FindByName per cercare un singolo allegato, Params per leggere i suoi metadati, e Delete/DeleteByKey per rimuoverlo.
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");Suggerimenti e migliori pratiche
- Preferisci
OptimizedMemoryStreamrispetto aMemoryStreamquando un documento in memoria può superare i 2GB –MemoryStreamgenera un’eccezione non appena il suo array di supporto unico raggiunge quel limite. - Rilascia le istanze
FileSpecification(e qualsiasi stream aperto manualmente per esse) –FileSpecificationimplementaIDisposable. - Verifica
Document.HasEmbeddedFilesprima di iterareEmbeddedFilesper saltare l’enumerazione non necessaria sui documenti senza allegati. - Imposta
MimeTypeeAFRelationshipsu ogniFileSpecificationaffinché i consumatori PDF a valle possano classificare correttamente gli allegati. - Usa
EmbeddedFileCollection.FindByNameper una singola ricerca per nome invece di scrivere un ciclo manuale.
Problemi comuni
| Problema | Causa | Correzione |
|---|---|---|
OutOfMemoryException salvataggio di un documento di grandi dimensioni su uno stream | MemoryStream è limitato a un singolo array di supporto di ~2 GB | Salva su OptimizedMemoryStream invece |
FileSpecification.GetData() restituisce un array vuoto | La posizione dello stream di origine non è stata ripristinata prima che FileSpecification fosse creato | Posizionare lo stream alla posizione 0 (o riaprirlo) prima di passarlo a FileSpecification |
EmbeddedFiles.FindByName restituisce null | Il nome dell’allegato non corrisponde esattamente (la ricerca è basata sul nome) | Itera doc.EmbeddedFiles e confronta i valori di Name, oppure verifica Keys |
| L’eliminazione di un allegato rimuove l’elemento sbagliato | Più allegati condividono lo stesso nome | Usa DeleteByKey con la chiave esatta di Keys per una rimozione inequivocabile |
FAQ
Qual è la differenza tra MemoryStream e OptimizedMemoryStream?
MemoryStream memorizza i suoi byte in un unico array contiguo limitato a circa 2 GB. OptimizedMemoryStream memorizza i dati in blocchi di dimensione fissa invece, così può superare tale limite – utile per le operazioni Document.Save eseguite interamente in memoria su file molto grandi.
Posso incorporare un file senza caricarlo prima in un byte[]?
Sì. FileSpecification(stream, name, description) accetta un Stream direttamente, quindi puoi incorporare da File.OpenRead(...) o da qualsiasi altro stream senza bufferizzarlo in memoria tu stesso.
Come faccio a recuperare un file incorporato da un documento?
Itera doc.EmbeddedFiles e chiama GetData() su ciascun FileSpecification per ottenere i byte grezzi.
Il metodo EmbeddedFileCollection.Delete(name) rimuove tutti gli allegati con quel nome?
No – individua un singolo allegato con precisione usando DeleteByKey e la chiave specifica da Keys se più allegati condividono lo stesso nome.
È sicuro riutilizzare FileSpecification su più documenti?
No. FileSpecification implementa IDisposable e avvolge un singolo stream di file incorporato; crea una nuova istanza per ogni allegato per documento.
API Reference Riepilogo
| Classe / Metodo | Descrizione |
|---|---|
OptimizedMemoryStream | Flusso in memoria espandibile che supera il limite di 2GB di MemoryStream |
OptimizedMemoryStream.Write | Scrivi i byte nel buffer |
OptimizedMemoryStream.ToArray | Restituisci i byte memorizzati nel buffer come array di byte |
FileSpecification | Descrittore di allegato file incorporato, basato su un flusso o dati byte |
FileSpecification.GetData | Recupera i byte grezzi di un file incorporato |
FileSpecification.Params | Metadati (dimensione, checksum, date) per il file incorporato |
EmbeddedFileCollection | Raccolta di allegati FileSpecification su un Document |
EmbeddedFileCollection.FindByName | Cerca un allegato per nome |
EmbeddedFileCollection.Delete | Rimuovi un allegato per nome |
Document.AddEmbeddedFile | Metodo di convenienza per incorporare un file da byte grezzi |
Document.EmbeddedFiles | La collezione di file incorporati del documento |
Document.HasEmbeddedFiles | Indica se il documento contiene file incorporati |
FileParams | Racchiude i metadati di dimensione/checksum/data per un flusso di file incorporato |