Le modèle d’adressage des conventions d’empaquetage ouvert

 

David Meltzer et Andrey Shur
Microsoft Corporation

Juin 2006

S’applique à :
   Open Packaging Conventions
   Microsoft Office 2007
   Microsoft Windows Vista
   Microsoft .NET Framework

Résumé: Cet article fournit une vue d’ensemble du modèle d’adressage utilisé dans open packaging Conventions, notamment la façon dont les packages et leurs composants sont traités, comment les références relatives dans les composants de package sont résolues et comment les applications peuvent utiliser le modèle d’adressage de package à l’aide du .NET Framework et des classes. (16 pages imprimées)

Contenu

Préface
Modèle d’adressage
Prise en charge de la programmation pour les URI « pack: »
Références

Préface

Dans le cadre de la conception d’Office 2007 et de Windows Vista, Microsoft a introduit les conventions open packaging. Ces conventions décrivent comment le contenu peut être organisé dans un « package ». Parmi les exemples de contenu, citons un document, une collection de médias et une bibliothèque d’applications. Les packages regroupent tous les composants du contenu en un seul objet.

Une application de traitement de texte peut utiliser des packages, par exemple, pour stocker les pages d’un document, les polices nécessaires et les images, graphiques et annotations sur les pages. Une application d’affichage ou de gestion de documents peut afficher uniquement des parties du contenu dans un package. Les applications peuvent utiliser un format basé sur un package, tel que XPS (XML Paper Specification), pour envoyer du contenu et des ressources à disposition fixe à une imprimante.

Cet article fournit une vue d’ensemble du modèle d’adressage utilisé dans open packaging Conventions, y compris la façon dont les packages et leurs parties sont traités, et comment les références relatives dans les composants de package sont résolues. Cet article explique également comment les applications peuvent utiliser le modèle d’adressage de package à l’aide des classes .NET Framework et .NET Framework 3.0. Cet article est principalement écrit pour les développeurs d’applications qui gèrent, produisent ou consomment des packages.

Pour obtenir des informations normatives complètes nécessaires à l’implémentation du modèle d’adressage de package, consultez la spécification des conventions d’open packaging. Les kits SDK .NET Framework 3.0 et .NET fournissent plus d’informations sur les classes et méthodes présentées.

Les documents présentés dans cette vue d’ensemble supposent une connaissance de base de la spécification d’URI. Les termes suivants sont utilisés selon RFC 3986 : URI, référence d’URI, composant de schéma, composant d’autorité, composant de chemind’accès, absolu du chemin d’accès et référence relative. Le terme URI désigne toujours la forme absolue d’un URI : le composant de schéma est présent et tous les autres composants correspondent à la grammaire propre au schéma. Le terme adressable, tel qu’utilisé ici, indique qu’il existe un URI qui identifie une ressource.

Modèle d’adressage

Les conventions open packaging définissent un modèle logique pour organiser le contenu et les ressources d’un package, et fournissent un mappage de ce modèle logique à une représentation physique, basée sur ZIP, XML et d’autres technologies disponibles.

Le modèle d’empaquetage logique décrit par Open Packaging Conventions définit une abstraction de package qui contient une collection de composants. Les parties peuvent avoir des relations entre elles, et le package peut avoir des relations avec des parties. Le modèle d’empaquetage spécifie comment les parties d’un package sont nommées, référencées et associées. Le modèle d’adressage défini par les conventions est la base de la possibilité de référencer et d’obtenir des ressources de partie dans un package.

Ressources de package adressables

Un package instance dans son ensemble est une ressource adressable, tout comme chaque partie contenue dans le package instance.

Traitement d’un package en tant qu’unité

Les applications peuvent utiliser un URI avec n’importe quel schéma (par exemple, « http: », « ftp: », etc.) pour traiter un package en tant qu’unité, en acquérant le flux de bits comprenant l’ensemble du package.

Les applications peuvent également traiter un package à l’aide du schéma d’URI « pack: » défini par open packaging Conventions. Ce schéma spécifie que l’URI complet identifiant le package est conservé dans le composant d’autorité d’un URI « pack: » sous une forme encodée.

Exemple : adressage d’un package

La ressource de package est traitée par les URI « http: » et « pack: » (respectivement) dans les exemples suivants :

http://www.site.com/windows/p1.xps

pack://http%3a,,www.site.com,windows,p1.xps/

Le type MIME de la ressource de package acquise indique le format de fichier du package, par exemple, il peut s’agir du format de document XPS (.xps), du format Office Open XML (.docx) ou d’un autre format conforme aux conventions open packaging.

Pour diverses raisons (telles que l’amélioration des performances), les applications peuvent utiliser un URI spécifique à leur domaine comme composant d’autorité d’un URI « pack: ». Un tel URI ne peut être résolu que dans le contexte d’une application donnée. La technique de programmation utilisée pour ces URI spécifiques à l’application est décrite plus loin, dans « The PackageStore ».

Adressage de parties dans un package

Les parties d’un package sont traitées à l’aide d’URI « pack: ». La structure d’un URI « pack: » qui traite un composant est la suivante : chemin d’accès pack://< autorité><>

Exemple : adressage de parties

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf adresse la partie nommée /fonts/arial.ttf, dans le package adressé par http://www.site.com/windows/p1.xps.

Le composant d’autorité contient l’URI encodé du package entier ; le composant path contient le nom du composant dans ce package. Les noms de parties sont conformes à la grammaire définie pour le composant URI path-absolute ([2], section 3.3), avec certaines restrictions supplémentaires ([1], section 2.1.1.1).

Exemple : Noms de composants

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

Les noms de parties sont des chaînes ASCII qui ne respectent pas la casse. Toutes les parties d’un package ont des noms uniques.

Utilisation d’identificateurs de fragment pour référencer des parties

Certaines applications qui utilisent open packaging Conventions peuvent référencer une partie à l’aide d’un URI non « pack: » d’une unité de package avec des identificateurs de fragments spécifiques au format.

Exemple : utilisation d’un URI non«pack: » pour référencer un composant

L’URI http://www.site.com/windows/p1.xps\#15 est utilisé pour référencer la partie qui représente la page 15 dans le document p1.xps ([3], sections 9.2.2 et 9.2.3).

Bien qu’il soit valide et, dans certains scénarios, utile d’avoir des URI autres que « pack: » faire référence à des parties, ces URI ne peuvent pas être utilisés comme URI de base pour résoudre les références relatives dans le contenu du composant.

Référence aux entrées dans des parties

Une partie est la ressource adressable la plus granulaire au sein d’un package. Toutefois, les applications peuvent avoir besoin de faire référence à des entrées dans le contenu d’un composant. Pour certains types de contenu, les entrées peuvent être référencées au moyen d’identificateurs de fragments ([2], section 3.5). Les conventions d’open packaging ne spécifient pas d’identificateurs de fragment. Les applications qui utilisent des identificateurs de fragments sont responsables de les traiter correctement.

Exemple : référencement d’entrées dans des parties

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#///[@Id="A012"] fait référence à un ensemble de nœuds XML dans le contenu du composant nommé /pages/page1.xaml et ayant la valeur d’attribut Id de A012.

Packages imbriqués

Les packages peuvent être imbriqués. Une partie d’un package peut contenir du contenu de n’importe quel type, y compris un package entier. Les parties d’un package imbriqué peuvent être traitées par un URI « pack: », avec un composant d’autorité qui indique la partie contenant ce package imbriqué ([1], Annexe D.3).

Exemple : adressage de parties dans des packages imbriqués

Un package situé dans http://www.site.com/package contient une partie nommée /nested-package

,

traité par le pack d’URI « pack : » ://http%3a,,www.site.com,package/nested-package.

La partie traitée par l’URI précédent contient une unité de package, qui contient une partie nommée /p1.xaml.

L’adresse de cette partie dans le package imbriqué est la suivante :

pack://pack%3a,,http:%253a%2cwww.site.com%2cpackage,nested-package/p1.xaml.

Références dans le contenu du composant

Les parties ayant certains types de contenu, tels que XML, peuvent contenir des références d’URI. Les références d’URI peuvent être des URI ou des références relatives. Les références d’URI peuvent être représentées dans le contenu par des chaînes Unicode. Les applications qui résolvent ces références d’URI doivent convertir les chaînes en un formulaire URI ([4], section 3.1).

Une référence relative est un URI exprimé par rapport à l’URI de base du contenu contenant la référence. L’URI de base par défaut pour le contenu du composant est l’URI « pack: » qui s’adresse à la partie.

Exemple : URI de base

L’URI de base d’un composant nommé /pages/page1.xaml dans un package adressé par http://www.site.com/windows/p1.xps est le suivant :

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml.

Si un AUTRE URI de base est nécessaire pour résoudre les références relatives dans les entrées du contenu du composant, une application doit spécifier explicitement l’autre. Certains types de contenu exposent certaines façons de spécifier l’URI de base de remplacement. Par exemple, XML utilise l’attribut xml:base , HTML utilise l’élément <de base> et Open Packaging Conventions utilisent l’attribut TargetMode pour les éléments Relationship .

L’utilisation de l’URI « pack: » d’une partie comme URI de base pour une référence relative garantit que la ressource référencée fera partie du même package ([2], section 5.2), sauf si la référence relative se trouve sous la forme de chemin d’accès réseau rarement utilisée (autrement dit, une référence relative commençant par « / »).

Exemple : Résolution d’une référence relative

Référence relative .. /.. /page2.xaml dans la partie adressée en tant que pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml est résolu en pack://http%3a,,www.site.com,windows,p1.xps/page2.xaml, en traitant la partie nommée /page2.xaml.

Les producteurs de packages peuvent utiliser des noms de parties comme forme valide de références relatives. Toutefois, lorsqu’ils utilisent des noms de composants comme références relatives, les producteurs doivent déterminer si les parties référencées peuvent également être traitées en tant que ressources extraites en dehors du package. Une fois les parties extraites d’un package, les noms de parties utilisés comme références relatives peuvent ne pas être résolus comme prévu. La barre oblique de début obligatoire pour les noms de parties, spécifiée par la grammaire des noms de partie, implique que ces références relatives sont résolues à partir de la racine de l’autorité actuelle.

Exemple : adressage des ressources extraites

Dans le contenu d’un composant nommé /doc1/pages/page1.xaml, la référence relative /page2.xaml adresse la partie nommée /page2.xaml, et la référence relative ./page3.xaml adresse le composant nommé /doc1/pages/page3.xaml.

Une fois que les parties /doc1/pages/page1.xaml, /doc1/pages/page3.xaml et /part2.xaml ont été extraites du package vers des fichiers nommés file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml et file:///c:/mydocs/page2.xaml (respectivement), la référence relative ./page3.xaml adresse le fichier file:///c:/mydocs/doc1/pages/page3.xaml, ce qui est attendu ; toutefois, la référence relative /page2.xaml traite désormais le fichier nommé file:///page2.xaml.

Références relatives dans les relations

Les conventions open packaging définissent les connexions entre les parties source et cible d’un package en tant que relations ([1], section 1.3).

Les relations sont regroupées et stockées en fonction de leurs sources. Une partie relations contient des relations qui proviennent du même composant source. Chaque relation est décrite par un élément XML dans le contenu de cette partie de relations. La partie relations est associée de manière unique à cette partie source (et inversement) à l’aide d’une convention de nommage définie pour la partie relations.

L’URI de base par défaut pour les URI spécifiés dans chaque élément Relationship est l’URI « pack: » de la partie source ([1], section 1.3.5). L’attribut TargetMode d’un élément Relationship indique l’URI de base pour la relation spécifiée.

Exemple : Élément de relation

L’élément de la partie relations qui définit une relation entre un composant source nommé /pages/page1.xaml et la partie cible /fonts/arial.ttf dans le même package peut se présenter comme suit :

<Type de relation= »https://schemas.microsoft.com/xps/2005/06/restricted-font"

TargetMode="Internal" Id="A123" Target=".. /fonts/arial.ttf"/>

La valeur interne de l’attribut TargetMode indique que l’URI de base de l’élément Relationship est la valeur par défaut pour le contenu de la partie relations, et identique à l’URI « pack: » de la partie source des relations. Dans l’exemple précédent, l’URI de base de l’élément Relationship est l’URI « pack: » de la partie /pages/page1.xaml .

Les relations peuvent également cibler des ressources externes par rapport à l’emplacement de l’ensemble du package.

Exemple : Relation avec la cible externe

Pour un package situé à file:///c:/office12/sample.docx, l’élément XML

<Id de relation="rId9 »

Type= »https://schemas.microsoft.com/office/2006/relationships/image"

Target="Icon.JPG » TargetMode="External"/>

définit la relation ciblant le fichier file:///c:/office12/icon.jpg.

La valeur externe de l’attribut TargetMode spécifie que la relation doit cibler une ressource en dehors du package. Si l’attribut Target contient une référence relative, un URI de base est requis. L’URI de base de cet élément de relation doit être l’URI de l’ensemble du package.

Délégation de références à des relations

Certains formats basés sur un package peuvent éviter d’utiliser des références d’URI dans le contenu, en déléguant les références aux relations. Cette technique de délégation est basée sur l’utilisation de valeurs ID uniques sur chaque élément Relationship pour mapper des références relatives dans le contenu d’une partie aux relations correspondantes.

Exemple : mappage de références relatives dans le contenu du composant à des relations

Un package situé à file:///c:/office12/sample.docx a une partie nommée /word/document.xml qui contient

<a:blip relEmbed="rId6 » relLink=" » w="0 » h="0"/>.

La partie relations attachée à cette partie contient l’élément

<Id de relation="rId6 »

Type= »https://schemas.microsoft.com/office/2006/relationships/image"

TargetMode="Internal » Target="media/image1.jpeg"/>.

Cela lie l’élément à la partie nommée /word/media/image1.jpeg.

L’avantage de cette approche est qu’une application peut identifier et gérer toutes les références au sein d’un package, sans examiner le contenu des parties.

Toutefois, si les références sont déléguées à des relations, il se peut que les parties de package extraites dans des fichiers libres ne fonctionnent pas correctement. Pour que les cibles de relation fonctionnent après l’extraction, une application consommatrice nécessite des connaissances spéciales sur les relations, des conventions d’emballage open pour nommer les parties de relation et la définition des URI de base pour les fichiers de relation.

Prise en charge de la programmation pour les URI « pack: »

Les applications qui produisent et/ou consomment des packages fonctionnent avec les adresses de package et de partie, et résolvent les références relatives dans le contenu des composants. .NET Framework 3.0, qui fournit l’ensemble d’API managées de nouvelle génération fournies par Microsoft, inclut des classes qui prennent en charge le modèle d’adressage des conventions open packaging. Ces classes permettent aux applications de composer et d’analyser des références et d’obtenir des ressources de package. La classe PackUriHelper est utilisée pour faciliter la gestion des URI « pack: ». La classe PackWebRequest est utilisée pour obtenir des ressources traitées à l’aide d’URI « pack: ».

Cette section illustre les fonctions que ces services effectuent dans la composition, l’analyse et la résolution des références.

Mise à disposition des services de package

Le .NET Framework version 3.0 (ou ultérieure) doit être installé pour pouvoir utiliser les classes des services d’empaquetage. Les classes se trouvent dans l’espace de noms System.IO.Packaging .

Avant d’utiliser System.Uri pour les opérations où des URI « pack: » sont impliqués, le schéma d’URI « pack: » doit être inscrit pour le domaine d’application. Le moyen le plus simple d’inscrire le schéma d’URI « pack: » consiste à appeler n’importe quelle méthode de la classe PackUriHelper . Le schéma peut également être inscrit, sans appeler la classe d’assistance, à l’aide de la méthode UriParser.Register , comme illustré dans l’exemple suivant. Toutefois, l’utilisation de cette méthode nécessite des autorisations de sécurité.

Exemple : Inscription du schéma d’URI « pack: »

//To register the "pack:" URI scheme without calling PackUriHelper

UriParser.Register(new GenericUriParser
   (GenericUriParserOptions.GenericAuthority),
      "pack", -1);

Obtention de l’URI « pack: » d’une ressource cible

Lors de la consommation d’un package, l’ensemble du package, ou une partie à la fois, peut être obtenu en tant qu’objet. Dans les deux cas, la méthode PackUriHelper.Create peut être utilisée pour créer l’URI « pack: » de la ressource de package ou de partie. Cet URI « pack: » est ensuite passé à la méthode PackWebRequest afin d’obtenir la ressource. PackWebRequest est décrit plus en détail dans la section suivante, « Obtention de ressources de package à l’aide de PackWebRequest ».

Un exemple courant de la façon dont les classes PackUriHelper et PackWebRequest peuvent être utilisées pour prendre en charge la consommation d’un package est détaillé dans les étapes suivantes. Si l’URI de package et l’URI de partie sont connus, une application peut :

  1. Composez un URI « pack: » à partir de l’URI du package et de l’URI de partie, à l’aide de PackUriHelper.
  2. Obtenez un flux de bits en appelant PackWebRequest.
  3. Chargez le contenu de la partie et analysez pour obtenir des références relatives.
  4. Résolvez ces références relatives par rapport à l’URI de base du composant (l’URI « pack: » composé à l’étape 1).
  5. Utilisez System.Uri pour résoudre les références relatives et utilisez PackWebRequest pour obtenir les ressources indiquées.

Création d’un URI « pack: » pour un package souhaité

L’URI « pack: » du package peut être créé à l’aide de la méthode PackUriHelper.Create .

Exemple : PackUriHelper.Create

//Given the URI for a package
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Use the Create method to create a "pack:" URI from a non-"pack:" URI
Uri packUri = PackUriHelper.Create(packageUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/"

L’URI « pack: » créé est passé à PackWebRequest afin d’obtenir la ressource de package.

Création d’un URI « pack: » pour un composant souhaité

L’URI « pack: » du composant peut être créé à l’aide de la méthode PackUriHelper.Create .

Exemple : PackUriHelper.Create

//Given the URI for package 
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Given the URI for a part
Uri partUri = new Uri("/sports.xml", UriKind.Relative);

//Use the PackUriHelper.Create method to create a "pack:" URI

Uri packUri = PackUriHelper.Create (packageUri, partUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/sports.xml"

L’URI « pack: » créé est passé à PackWebRequest afin d’obtenir la ressource de composant.

Résolution des références relatives

Lors du traitement du contenu d’un composant, il est possible de trouver des références relatives qui font référence à d’autres parties ou ressources. La résolution de ces références est une première étape de l’obtention des ressources référencées.

Une référence relative dans le contenu d’un composant est résolue par rapport à l’URI de base d’une partie à l’URI « pack: » du composant cible. L’URI « pack: » du composant cible est passé à PackWebRequest afin d’obtenir la ressource de composant à partir du package. Le nom d’un composant cible, dérivé de l’URI « pack: » de la partie cible, peut également être utilisé pour obtenir un composant ciblé, en passant le nom de la partie à la méthode Package.GetPart .

Lors de la résolution des références relatives aux composants cibles, la résolution peut emprunter plusieurs chemins, selon les informations disponibles au début et si le package est ouvert (ou peut être ouvert). Deux de ces chemins d’accès sont les suivants :

  • Au début :

    1. L’URI « pack: » de la partie contenant la référence est connu.
    2. Le package n’est pas ouvert.
    //Given the "pack:" URI for the part "/files/fixeddoc.xaml"
    //packUri =
    // "pack://http%3a,,www.newsdocs.com,local,today.container
    // /files/fixeddoc.xaml"
    
    //The part "/files/fixeddoc.xaml" contains 
    //the relative reference "../images/1.jpg"
    
    Uri relativeReference = new Uri("../images/1.jpg", 
                      UriKind.Relative);
    
    //Use System.Uri to directly obtain the absolute target URI
    
    Uri targetPackUri = new Uri(packUri, relativeReference);
    
    //The value of the resulting targetPackUri is 
    //"pack://http%3a,,www.newsdocs.com,local,today.container
    // /images/1.jpg"
    
    //Now another PackWebRequest can be made using 
    //this targetPackUri value.
    
  • Au début :

    1. Le nom de la partie contenant la référence est connu.
    2. Le package est ouvert.
    //Given "package" as the current instance of the Package class.
    //Given the relative reference = "../../images/1.jpg"
    
    Uri relativeReference = new Uri("../../images/1.jpg", 
                      UriKind.Relative);
    
    //Given the URI of the part that contains the relative reference
    
    Uri partUri = new Uri("/files/fixeddoc.xaml");
    
    //Use PackUriHelper.ResolvePartUri to obtain the resolved part URI 
    //of the target based on the part URI above and the relative 
    //reference in that part
    
    Uri targetPartUri = PackUriHelper.ResolvePartUri
                   (partUri, relativeReference);
    
    //The resulting targetPartUri value is "fixeddoc.xaml"
    //Now use the package.GetPart method to obtain the target part
    
    PackagePart packagePart = package.GetPart(targetPartUri);
    

Fourniture de noms de parties à la classe de package

Une fois qu’un package est ouvert, la classe Package est utile pour ajouter des parties aux packages, obtenir des parties et supprimer des parties. Les méthodes de la classe Package , telles que Package.AddPart, Package.DeletePart et Package.GetPart, prennent un URI de partie comme paramètre. La méthode PackUriHelper.CreatePartUri peut être utilisée pour créer un nom de composant valide à partir d’une référence relative à l’URI de base du package.

Exemple : PackUriHelper.CreatePartUri

//Given a URI

Uri partUri = PackUriHelper.CreatePartUri 
            (new Uri "files/a.xaml",UriKind.Relative))

//The URI will be checked for validity, and a leading slash
//will be added. The resulting partUri value is "/files/a.xaml"

Service de génération de références relatives

Une application de création peut avoir besoin de dériver une référence relative qui, lorsqu’elle est placée dans le contenu d’un composant source, pointe vers un composant cible. La méthode GetRelativeUri remplit cet objectif.

Exemple : Exemple GetRelativeUri

//Given the URI of the source part

Uri sourcePartUri = new Uri("/tiles/pages/a.xaml", UriKind.Relative);

//Given the URI of the target part

Uri targetPartUri = new Uri("/images/event1/1.jpg", UriKind.Relative);

//Use PackUriHelper.GetRelativeUri to generate the relative reference
//that will be placed in the content of the source part.

Uri relativeReference = PackUriHelper.GetRelativeUri
               (sourcePartUri, targetPartUri);

//The resulting relativeReference value is "../../images/event1/1.jpg"

Obtention de ressources de package à l’aide de PackWebRequest

Les applications peuvent obtenir des packages et des ressources de composants à l’aide de PackWebRequest, une classe dérivée de System.Net.WebRequest. PackWebRequest retourne une ressource adressée par un URI « pack: » donné.

En général, le lancement d’une demande PackWebRequest pour un URI « pack: » se compose des étapes suivantes :

  1. La grammaire de l’URI « pack: » est vérifiée.
  2. Le composant d’autorité est extrait de l’URI « pack: » et vérifié pour voir s’il suit la grammaire d’un URI absolu.
  3. Si le composant de chemin d’accès de l’URI « pack: » est vide :
  • Le flux de package est obtenu pour le composant d’autorité et retourné à l’appelant.

    Sinon, si le composant de chemin d’accès n’est pas vide :

    1. Le package ouvert est obtenu pour la ressource identifiée par le composant d’autorité. En fonction de l’ensemble CachePolicy , PackWebRequest obtient un package ouvert à partir du PackageStore ou crée une webRequest interne pour la ressource de package et ouvre le package à partir du flux de package retourné.
    2. La partie est obtenue à l’aide du composant de chemin d’accès de l’URI « pack: » comme nom de partie.
    3. Le flux de pièce est obtenu et retourné à l’appelant.

PackWebResponse.GetStream retourne un flux de bits représentant soit l’ensemble du package (un flux de package) soit une seule partie d’un package (un flux de partie).

Contrairement à la plupart des flux WebResponse, un flux de package peut être recherché à l’aide de Stream.Seek. Un flux de package peut être utilisé pour créer un objet de package.

Lors de l’utilisation d’une ressource de package via un protocole « http: », PackWebRequest prend en charge le chargement progressif des parties , c’est-à-dire la possibilité d’obtenir des ressources de partie dans un ordre arbitraire, sans charger toutes les données du package jusqu’aux données de partie.

PackWebRequest fournit uniquement des installations pour la consommation des ressources. Il ne peut pas être utilisé pour publier ou envoyer des données à un serveur.

PackWebRequest ne prend actuellement pas en charge les opérations asynchrones (telles que BeginGetResponse) et PackWebRequest ne prend pas en charge les packages imbriqués (décrit précédemment dans « Adressage de parties au sein d’un package »).

The PackageStore

Lors du chargement de packages contenant de nombreuses références à d’autres parties, le temps de réponse aux demandes de ressources peut être amélioré et le trafic réseau peut être réduit à l’aide du PackageStore. PackageStore est un dictionnaire d’application local de références permettant d’ouvrir des packages. Chaque package inscrit dans le PackageStore est identifié par une valeur d’URI de clé.

Le PackageStore permet à PackWebRequest d’obtenir les ressources nécessaires à partir d’un package, sans effectuer de demande de serveur chaque fois qu’une autre ressource est nécessaire à partir de ce package.

Le PackageStore n’est pas modifié automatiquement à la suite d’un appel à PackWebRequest. Il doit être modifié explicitement. Il existe deux méthodes publiques utilisées pour ajouter ou supprimer des références à l’ouverture de packages dans le PackageStore : Package.AddPackage et Package.RemovePackage.

La stratégie de cache par défaut (CacheIfAvailable) définie sur PackWebRequest oblige la classe à tenter d’utiliser le PackageStore pour obtenir le package. PackWebRequest peut être forcé d’ignorer le contenu du PackageStore lors de l’obtention de ressources, en définissant la stratégie de cache sur BypassCache, comme décrit dans la section suivante, « Stratégies de cache ».

Lors de l’obtention des bits d’un package ou d’une partie conformément à la stratégie de cache par défaut, PackWebRequest vérifie d’abord le PackageStore pour voir s’il existe un package inscrit avec une clé égale au composant d’autorité de l’URI « pack: ». Si le PackageStore ne contient pas le package de la clé, PackWebRequest crée un WebRequest interne pour télécharger la ressource à l’aide du composant d’autorité de l’URI « pack: ».

Stratégies de cache

Les stratégies de cache définissent les règles utilisées pour déterminer si une demande de ressource peut être remplie à l’aide d’une copie mise en cache de la ressource.

Lors de l’utilisation de PackWebRequest, il existe deux niveaux de stratégie de cache qui peuvent être définis explicitement. Une stratégie de cache peut être définie pour le PackWebRequest lui-même, contrôlant l’interaction avec le PackageStore. Une stratégie de cache peut également être définie pour le cache contrôlé par une requête WebRequest interne. PackWebRequest interne est accessible à l’aide de PackWebRequest.GetInternalRequest().

La stratégie de cache définie sur le WebRequest interne n’aura aucun effet si PackWebRequest.CachePolicy est défini sur CacheOnly, ce qui entraîne l’obtention de la ressource de package à partir du PackageStore.

PackWebRequest.CachePolicy prend en charge un sous-ensemble de stratégies, comme indiqué ci-dessous, en raison des fonctionnalités spécifiques du PackageStore.

Tableau 1. Stratégies PackWebRequest.CachePolicy

CachePolicy Description
BypassCache Ignorez les entrées PackageStore avec un URI correspondant.
CacheOnly Tenez uniquement compte des entrées PackageStore (ne créez jamais de WebRequest pour interroger le serveur pour obtenir des données).
CacheIfAvailable Inspectez le PackageStore et utilisez n’importe quel package s’il y en a un ; sinon, effectuez une demande réseau à la ressource indiquée par l’URI du package (l’URI interne de l’URI « pack: »). Il s’agit de la valeur par défaut.

Pour PackWebRequest, la définition de toutes les autres valeurs CachePolicy entraîne une WebException.

Chargement progressif

PackWebRequest peut charger progressivement un composant de package lorsque le package est accessible via le protocole « http: ». Le chargement progressif permet aux applications d’accéder aux ressources de partie avant que l’ensemble du package soit disponible localement. La fonctionnalité de chargement progressif de PackWebRequest est automatique : l’application appelante affiche des performances améliorées sans intervenir.

Le chargement progressif est basé sur l’envoi de « requêtes de plage d’octets » pour les ressources, comme défini dans le protocole « http: » 1.1. Le format de fichier ZIP, utilisé pour stocker des packages sous forme physique, bénéficie de ce mécanisme, car le format d’archive ZIP conserve les informations importantes dans un « répertoire central » à la fin physique du fichier.

Après avoir demandé un package entier à l’aide de PackWebRequest, le service commence à renvoyer un flux sur lequel un appelant peut rechercher. Lorsqu’un package est ouvert sur le flux fourni par PackWebRequest, l’appelant peut obtenir des parties plus rapidement que lors de requêtes directes à l’aide, par exemple, du protocole « http: ».

Services pour l’évaluation et la décomposition des URI

Identification des noms de parties de relation retournés par la classe de package

Lors de la gestion d’une collection de composants obtenue à l’aide de la méthode Package.GetParts, les parties de relation peuvent être identifiées afin qu’elles puissent être gérées séparément des autres parties. PackUriHelper.IsRelationshipPartUri permet d’identifier si une partie est une partie de relation.

Exemple : PackUriHelper.IsRelationshipPartUri

//Given the URI for a part

Uri partUri = new Uri("/_rels/sports.rels", UriKind.Relative);

bool isRelationshipPart = PackUriHelper.IsRelationshipPartUri(PartUri);

//The resulting isRelationshipPart value is "TRUE"

Deux autres méthodes PackUriHelper sont disponibles pour utiliser des noms de parties de relation. PackUriHelper.GetRelationshipPartUri retourne un nom de partie de relation donné à un nom de partie source. PackUriHelper.GetSourcePartUriFromRelationshipPartUri retourne le nom du composant source pour un nom de partie de relation donné.

Comparaison des URI pour l’équivalence

Une application qui utilise un cache pour stocker des pièces lors de la production ou de la consommation d’un package peut avoir besoin d’effectuer des vérifications pour les noms de composants équivalents. La méthode PackUriHelper.ComparePartUri vérifie l’équivalence des noms de parties.

Exemple : PackUriHelper.ComparePartUri

//Given two part names in the same package
//firstPartName = "/a.xaml"
//secondPartName = "/A.xaml"

//Use PackUriHelper.ComparePartUri to identify if the names 
//are equivalent.

Bool isSamePartName = PackUriHelper.ComparePartUri 
               (firstPartName, secondPartName);

//The resulting isSamePartName value is "TRUE"

Pour déterminer l’équivalence lexicale de deux URI « pack: », utilisez la méthode PackUriHelper.ComparePackUriUri .

Exemple : PackUriHelper.ComparePackUriUri

//Given two "pack:" URIs
//firstPackUri =
// "PACK://HTTP%3A,,WWW.NEWSDOCS.COM,local,today.container
// /FILES/FIXEDDOC.XAML"
//secondPackUri = 
// "pack://http%3a,,www.newsdocs.com,local,today.container
// /files/fixeddoc.xaml"

//Use PackUriHelper.ComparePackUri to identify if the same resource 
//is targeted.

bool isSameResource = PackUriHelper.ComparePackUri 
            (firstPackUri, secondPackUri);

//The resulting isSameResource value is "TRUE"

Extraction d’URI de composant à partir d’un URI « pack: »

Pour extraire l’URI de package de composant et l’URI de composant à partir d’un URI « pack: », utilisez les méthodes PackUriHelper.GetPackageUriUri et PackUriHelper.GetPartUri, respectivement.

Exemple : PackUriHelper.GetPackageUriUri

//Given the "pack:" URI for a package

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
            /files/abc.xaml";

//Use PackUriHelper.GetPackageUri to obtain the URI of the package

Uri packageUri = new PackUriHelper.GetPackageUri(packUri);

//The resulting packageUri value is
//"http://www.newsdocs.com/local/today.container"

Exemple : Exemple GetPartUri

//Given the "pack:" URI for a part

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
         /files/abc.xaml";

//Use PackUriHelper.GetPartUri to obtain the URI of the part

Uri partUri = new PackUriHelper.GetPartUri(packUri);

//The resulting partUri value is "/files/abc.xaml"

Références

Open Packaging Conventions

URI (Uniform Resource Identifier) : syntaxe générique

Open XML Paper Specification

Identificateurs de ressources internationalisés (IRIs)