Un PDF peut contenir d’autres fichiers à l’intérieur. Il peut s’agir d’un portefeuille qui regroupe des contrats et des feuilles de calcul, ou d’un rapport avec ses données sources jointes. Lorsque vous extrayez ces fichiers dans le code, vous souhaitez que chacun soit enregistré sous le nom donné par son auteur, et non sous attachment1.bin. Ce tutoriel montre comment extraire les fichiers intégrés d’un PDF avec leurs noms d’origine en C# en utilisant Aspose.PDF for .NET. Vous ouvrirez un PDF, parcourrez ses fichiers intégrés, résoudrez le nom de chaque fichier avec FileSpecification.GetFileName, et écrirez le contenu dans un dossier.

Où un PDF stocke le nom d’un fichier incorporé

Chaque fichier intégré est décrit par une spécification de fichier, et une spécification de fichier peut enregistrer le nom à plusieurs endroits. Il existe un nom de fichier Unicode, un nom de fichier standard, et la clé sous laquelle le fichier est répertorié dans la collection de fichiers intégrés du document. Les producteurs de PDF ne remplissent pas ces informations de manière cohérente, et certains omettent complètement le nom.

Aspose.PDF for .NET fournit la propriété FileSpecification.GetFileName pour gérer cela. Il résout le nom à partir du nom Unicode, du nom de fichier ordinaire ou de la clé de collection, selon ce qui est disponible, de sorte que vous obtenez toujours un nom utilisable lorsque le nom Unicode est absent. Vous pouvez fournir un nom de secours pour les fichiers qui n’ont aucun nom. Un deuxième paramètre optionnel contrôle si un nom vide est autorisé lorsqu’aucun nom de fichier n’est disponible. Vous obtenez un seul appel au lieu de votre propre logique de lecture des dictionnaires PDF.

Remarque : les exemples de cet article n’utilisent que l’argument de secours.

Le Document.EmbeddedFiles contient les pièces jointes au niveau du document, ce qui inclut les fichiers d’un portefeuille PDF. Les fichiers attachés à une page spécifique via une annotation de pièce jointe (généralement affichée sous forme d’icône trombone) sont stockés sur l’annotation ; Extract files attached to pages couvre ces cas.

Utilisation d’Aspose.PDF pour extraire des fichiers intégrés d’un PDF

Install-Package Aspose.PDF

Ou avec le .NET CLI:

dotnet add package Aspose.PDF
  • Un PDF qui contient des fichiers intégrés. L’exemple utilise un portfolio nommé PDFPortfolio.pdf.

Sans licence, Aspose.PDF s’exécute en mode d’évaluation. Pour tester sans restrictions d’évaluation, demandez une licence temporaire gratuite.

Extraire chaque fichier incorporé avec son nom d’origine

La méthode suivante ouvre le PDF, enregistre chaque fichier incorporé dans un dossier de sortie sous son nom résolu, et affiche le chemin de chaque fichier qu’elle écrit.

using System;
using System.IO;
using Aspose.Pdf;

public static class EmbeddedFileExtractor
{
    public static void ExtractEmbeddedFiles(string inputPdf, string outputDir)
    {
        Directory.CreateDirectory(outputDir);

using (var document = new Document(inputPdf))
        {
            foreach (FileSpecification fileSpec in document.EmbeddedFiles)
            {
                // Resolve the stored name, then keep only the file name part.
                string fileName = Path.GetFileName(fileSpec.GetFileName("attachment.bin"));
                string outputPath = Path.Combine(outputDir, fileName);

using (var output = new FileStream(outputPath, FileMode.Create))
                {
                    fileSpec.Contents.CopyTo(output);
                }

Console.WriteLine($"Saved: {outputPath}");
            }
        }
    }
}

Appelez‑le avec le chemin du PDF et le dossier où vous voulez les fichiers :

EmbeddedFileExtractor.ExtractEmbeddedFiles("PDFPortfolio.pdf", "ExtractedFiles");

Ce que chaque étape fait

Ouvrez le document. new Document(inputPdf) charge le PDF. Le bloc using libère le handle du fichier lorsque le traitement se termine, même si une exception est levée.

Parcourir les pièces jointes. document.EmbeddedFiles renvoie un FileSpecification pour chaque fichier intégré au niveau du document.

Résoudre le nom. fileSpec.GetFileName("attachment.bin") renvoie le nom stocké, ou attachment.bin si le PDF n’en fournit aucun. Choisissez une valeur de secours qui a du sens pour votre application.

Supprimer les segments de dossier. Un nom stocké peut inclure un chemin tel que reports/2026/q3.xlsx, ou une valeur manipulée telle que ..\..\startup.bat. Passer le résultat à travers Path.GetFileName le réduit à q3.xlsx ou startup.bat, de sorte que le fichier ne puisse pas être écrit en dehors de outputDir. Conservez cette étape même si vous faites confiance aux PDF que vous traitez aujourd’hui.

Écrire le contenu. fileSpec.Contents est un flux des données du fichier incorporé. CopyTo l’écrit dans le nouveau fichier sans aucune conversion.

Résultat attendu

Le dossier de sortie contient un fichier pour chaque pièce jointe au niveau du document, nommé tel qu’il était stocké dans le PDF. Pour un portefeuille contenant une feuille de calcul et un document Word, la sortie de la console ressemble à ceci :

Saved: ExtractedFiles\budget-2026.xlsx
Saved: ExtractedFiles\service-agreement.docx

Les noms de fichiers dépendent de votre PDF. Les fichiers extraits contiennent les mêmes données que celles qui ont été intégrées, de sorte que chacun s’ouvre dans l’application qui gère son format.

Gérer les noms en double et non sécurisés

L’exemple de base présente trois points faibles que vous rencontrerez avec les PDF du monde réel :

  • Deux pièces jointes peuvent partager le même nom, et FileMode.Create écrase silencieusement la première. Cela se produit également lorsque plusieurs pièces jointes n’ont pas de nom et reviennent toutes à attachment.bin.
  • Un nom qui est valide sur un système d’exploitation peut contenir des caractères invalides sur un autre, comme : sous Windows.
  • Un nom stocké qui se termine par un séparateur de chemin laisse Path.GetFileName renvoyer une chaîne vide.

Cet assistant gère les trois cas. Il remplace les caractères invalides, revient à une valeur par défaut lorsque le nom est vide, et ajoute un compteur lorsque le fichier existe déjà :

private static string GetSafeOutputPath(string outputDir, string resolvedName, string fallbackName)
{
    string fileName = Path.GetFileName(resolvedName);

foreach (char c in Path.GetInvalidFileNameChars())
    {
        fileName = fileName.Replace(c, '_');
    }

if (string.IsNullOrWhiteSpace(fileName))
    {
        fileName = fallbackName;
    }

string baseName = Path.GetFileNameWithoutExtension(fileName);
    string extension = Path.GetExtension(fileName);
    string outputPath = Path.Combine(outputDir, fileName);

int counter = 1;
    while (File.Exists(outputPath))
    {
        outputPath = Path.Combine(outputDir, $"{baseName} ({counter}){extension}");
        counter++;
    }

return outputPath;
}

Dans la boucle d’extraction, remplacez les deux lignes qui construisent fileName et outputPath par :

string outputPath = GetSafeOutputPath(outputDir, fileSpec.GetFileName("attachment.bin"), "attachment.bin");

Comme l’assistant vérifie les fichiers existants, exécuter l’extraction deux fois dans le même dossier crée des copies numérotées plutôt que d’écraser les fichiers. Videz le dossier d’abord si vous souhaitez un résultat frais à chaque exécution.

Extraire les fichiers joints aux pages

Si EmbeddedFiles est vide mais que vous voyez une icône de trombone dans un visualiseur PDF, le fichier est probablement attaché via une annotation de pièce jointe de fichier sur une page. L’annotation possède son propre FileSpecification dans la propriété File, de sorte que la même résolution de nom et le même assistant s’appliquent. Cette méthode parcourt chaque page et enregistre chaque fichier joint dans le dossier de sortie :

using Aspose.Pdf.Annotations;

public static void ExtractPageAttachments(string inputPdf, string outputDir)
{
    Directory.CreateDirectory(outputDir);

using (var document = new Document(inputPdf))
    {
        foreach (Page page in document.Pages)
        {
            foreach (Annotation annotation in page.Annotations)
            {
                if (annotation is FileAttachmentAnnotation attachment && attachment.File != null)
                {
                    string outputPath = GetSafeOutputPath(outputDir, attachment.File.GetFileName("attachment.bin"), "attachment.bin");

using (var output = new FileStream(outputPath, FileMode.Create))
                    {
                        attachment.File.Contents.CopyTo(output);
                    }

Console.WriteLine($"Saved: {outputPath}");
                }
            }
        }
    }
}

Pour collecter chaque pièce jointe dans un PDF, exécutez les deux méthodes avec le même dossier de sortie. Si un PDF fait référence au même fichier depuis les deux emplacements, GetSafeOutputPath enregistre la deuxième copie avec un nom numéroté plutôt que d’écraser la première.

Prochaines étapes

Pour aller plus loin avec les pièces jointes, comme l’ajout, la suppression ou la liste sans extraction, consultez la documentation Aspose.PDF for .NET. La référence de la classe FileSpecification répertorie les propriétés other name et description que vous pouvez lire pour chaque fichier intégré. Si un PDF ne s’extrait pas comme prévu, publiez un exemple dans le forum de support Aspose.PDF.

FAQs

  1. Comment FileSpecification.GetFileName choisit‑il un nom ? Il résout le nom à partir du nom Unicode du fichier incorporé, du nom de fichier ordinaire ou de la clé de la collection, selon ce qui est disponible. Si aucun n’est disponible, il renvoie le nom de secours que vous fournissez. La méthode a été ajoutée dans Aspose.PDF for .NET 26.9.

  2. Cela fonctionne-t-il pour les PDF qui ne sont pas des portfolios ? Oui, pour les fichiers attachés au niveau du document. Les fichiers attachés à une page spécifique via une annotation de pièce jointe (généralement affichée sous forme d’icône trombone) sont stockés sur l’annotation, il faut donc les lire à partir de FileAttachmentAnnotation.File, comme indiqué dans Extraire les fichiers attachés aux pages.

  3. Pourquoi envelopper le résultat de GetFileName dans Path.GetFileName ? Le nom stocké dans un PDF est défini par la personne qui a créé le fichier et peut inclure des segments de dossiers. Path.GetFileName ne conserve que le nom du fichier, de sorte que chaque pièce jointe est écrite dans votre dossier de sortie.

  4. Que se passe-t-il si deux pièces jointes portent le même nom ? Avec FileMode.Create, le deuxième fichier écrase le premier. Vérifiez si le chemin existe déjà et ajoutez un suffixe numérique, comme indiqué dans Gérer les noms en double et non sécurisés.

  5. Puis-je traiter une pièce jointe sans l’enregistrer sur le disque ?
    Oui. La propriété Contents est un Stream, vous pouvez donc la copier dans un MemoryStream, la télécharger ou la transmettre à une autre bibliothèque au lieu de l’écrire dans un FileStream.