Share via


Modello di indirizzamento delle convenzioni open packaging

 

David Meltzer e Andrey Shur
Microsoft Corporation

Giugno 2006

Si applica a:
   Open Packaging Conventions
   Microsoft Office 2007
   Microsoft Windows Vista
   Microsoft .NET Framework

Riepilogo: Questo articolo fornisce una panoramica del modello di indirizzamento usato nelle Convenzioni open packaging, tra cui il modo in cui vengono risolti i pacchetti e le relative parti, il modo in cui vengono risolti i riferimenti relativi nelle parti del pacchetto e come le applicazioni possono usare il modello di indirizzamento dei pacchetti con l'aiuto delle classi e di .NET Framework. (16 pagine stampate)

Contenuto

Prefazione
Modello di indirizzamento
Supporto per la programmazione per gli URI "pack:"
Riferimenti

Prefazione

Nell'ambito della progettazione di Office 2007 e Windows Vista, Microsoft ha introdotto Open Packaging Conventions. Queste convenzioni descrivono come organizzare il contenuto in un "pacchetto". Alcuni esempi di contenuto includono un documento, una raccolta di supporti e una raccolta di applicazioni. I pacchetti aggregano tutti i componenti del contenuto in un singolo oggetto.

Un'applicazione per l'elaborazione di parole può usare pacchetti, ad esempio, per archiviare le pagine di un documento, i tipi di carattere necessari e le immagini, i grafici e le annotazioni nelle pagine. Un'applicazione di visualizzazione o gestione di documenti può visualizzare solo parti del contenuto in un pacchetto. Le applicazioni possono usare un formato basato su pacchetto, ad esempio XPS (XML Paper Specification), per inviare contenuto e risorse a layout fisso a una stampante.

Questo articolo fornisce una panoramica del modello di indirizzamento usato nelle Convenzioni open packaging, tra cui il modo in cui vengono risolti i pacchetti e le relative parti e come vengono risolti i riferimenti relativi nelle parti del pacchetto. Questo articolo illustra anche come le applicazioni possono usare il modello di indirizzamento dei pacchetti con l'aiuto delle classi .NET Framework e .NET Framework 3.0. Questo articolo viene scritto principalmente per gli sviluppatori di applicazioni che gestiranno, produrranno o utilizzeranno pacchetti.

Per informazioni normative complete necessarie per implementare il modello di indirizzamento dei pacchetti, vedere la specifica per Open Packaging Conventions. Gli SDK .NET Framework 3.0 e .NET forniscono altre informazioni sulle classi e sui metodi descritti.

Il materiale presentato in questa panoramica presuppone una conoscenza di base della specifica dell'URI. I termini seguenti vengono usati in base a RFC 3986: URI, riferimento URI, componente dello schema, componente autorità, componente delpercorso, percorso-assoluto e riferimento relativo. Il termine URI indica sempre la forma assoluta di un URI, ovvero il componente dello schema è presente e tutti gli altri componenti corrispondono alla grammatica specifica dello schema. Il termine indirizzabile, come usato qui, indica che esiste un URI che identifica una risorsa.

Modello di indirizzamento

Open Packaging Conventions definisce un modello logico per organizzare il contenuto e le risorse di un pacchetto e fornire un mapping da questo modello logico a una rappresentazione fisica, in base a ZIP, XML e altre tecnologie openly disponibili.

Il modello di creazione di pacchetti logici descritto da Open Packaging Conventions definisce un'astrazione del pacchetto che contiene una raccolta di parti. Le parti possono avere relazioni tra loro e il pacchetto può avere relazioni con le parti. Il modello di creazione del pacchetto specifica il modo in cui le parti di un pacchetto vengono denominate, a cui viene fatto riferimento e correlate. Il modello di indirizzamento definito dalle convenzioni è la base per poter fare riferimento e ottenere risorse di parte in un pacchetto.

Risorse del pacchetto indirizzabili

Un'istanza del pacchetto nel suo complesso è una risorsa indirizzabile, come ogni parte contenuta nell'istanza del pacchetto.

Indirizzamento di un pacchetto come unità

Le applicazioni possono usare un URI con qualsiasi schema ,ad esempio "http:", "ftp:" e così via, per gestire un pacchetto come unità, acquisendo il flusso di bit che comprende l'intero pacchetto.

Le applicazioni possono anche gestire un pacchetto usando lo schema URI "pack:" definito da Open Packaging Conventions. Questo schema specifica che l'URI completo che identifica il pacchetto viene mantenuto nel componente dell'autorità di un URI "pack:" in un modulo codificato.

Esempio: Indirizzamento di un pacchetto

La risorsa del pacchetto viene indirizzata rispettivamente dagli URI "http:" e "pack:" negli esempi seguenti:

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

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

Il tipo MIME della risorsa del pacchetto acquisito indica il formato di file del pacchetto, ad esempio il formato XPS Document (.xps), il formato Office Open XML (.docx) o un altro formato conforme alle Convenzioni open packaging.

Per vari motivi,ad esempio per migliorare le prestazioni, le applicazioni possono usare un URI specifico per il proprio dominio come componente dell'autorità di un URI "pack:". Tale URI è risolvibile solo nel contesto di una determinata applicazione. La tecnica di programmazione usata per tali URI specifici dell'applicazione è descritta più avanti in "PackageStore".

Indirizzamento di parti all'interno di un pacchetto

Le parti di un pacchetto vengono indirizzate usando gli URI "pack:". La struttura di un URI "pack:" che punta a una parte è la seguente: pack://< percorso di autenticazione><>

Esempio: Indirizzamento di parti

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf punta alla parte denominata /fonts/arial.ttf, nel pacchetto a cui fa riferimento http://www.site.com/windows/p1.xps.

Il componente autorità contiene l'URI codificato dell'intero pacchetto; il componente path contiene il nome della parte nel pacchetto. I nomi delle parti sono conformi alla grammatica definita per il componente URI assoluto del percorso ([2], sezione 3.3), con alcune restrizioni aggiuntive ([1], sezione 2.1.1.1).

Esempio: Nomi delle parti

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

I nomi delle parti sono stringhe ASCII senza distinzione tra maiuscole e minuscole. Tutte le parti di un pacchetto hanno nomi univoci.

Uso degli identificatori di frammento per fare riferimento alle parti

Alcune applicazioni che usano Open Packaging Conventions possono fare riferimento a una parte usando un URI non"pack:" di un'unità di pacchetto con identificatori di frammento specifici del formato.

Esempio: uso di un URI non"pack:" per fare riferimento a una parte

L'URI http://www.site.com/windows/p1.xps\#15 viene usato per fare riferimento alla parte che rappresenta la pagina 15 nel documento p1.xps ([3], sezioni 9.2.2 e 9.2.3).

Sebbene sia valido e, per determinati scenari, utile avere URI non "pack:" fanno riferimento a parti, tali URI non possono essere usati come URI di base per risolvere i riferimenti relativi nel contenuto della parte.

Riferimento alle voci all'interno di parti

Una parte è la risorsa indirizzabile più granulare all'interno di un pacchetto. Tuttavia, le applicazioni potrebbero dover fare riferimento alle voci all'interno del contenuto di una parte. Per determinati tipi di contenuto, è possibile fare riferimento alle voci tramite identificatori di frammento ([2], sezione 3.5). Le convenzioni open packaging non specificano identificatori di frammento. Le applicazioni che usano identificatori di frammento sono responsabili dell'elaborazione corretta.

Esempio: riferimento a voci all'interno di parti

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] fa riferimento a un set di nodi XML all'interno del contenuto della parte denominata /pages/page1.xaml e con il valore dell'attributo IdA012.

Pacchetti annidati

I pacchetti possono essere annidati. Una parte di un pacchetto può contenere contenuto di qualsiasi tipo, incluso un intero pacchetto. Le parti di un pacchetto annidato possono essere indirizzate da un URI "pack:", con un componente dell'autorità che indica la parte che contiene questo pacchetto annidato ([1], Appendice D.3).

Esempio: indirizzamento di parti nei pacchetti annidati

Un pacchetto che si trova in http://www.site.com/package contiene una parte denominata /nested-package

,

indirizzato dall'URI "pack:" pack://http%3a,,www.site.com,package/nested-package.

La parte indirizzata dall'URI precedente contiene un'unità del pacchetto, che contiene una parte denominata /p1.xaml.

L'indirizzo di questa parte nel pacchetto annidato è il seguente:

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

Riferimenti nel contenuto della parte

Le parti con determinati tipi di contenuto, ad esempio XML, possono contenere riferimenti URI. I riferimenti URI possono essere URI o riferimenti relativi. I riferimenti URI possono essere rappresentati nel contenuto da stringhe Unicode. Le applicazioni che risolvono tali riferimenti URI devono convertire le stringhe in un formato URI ([4], sezione 3.1).

Un riferimento relativo è un URI espresso rispetto all'URI di base del contenuto contenente il riferimento. L'URI di base predefinito per il contenuto della parte è l'URI "pack:" che punta alla parte.

Esempio: URI di base

L'URI di base per una parte denominata /pages/page1.xaml in un pacchetto indirizzato da http://www.site.com/windows/p1.xps è il seguente:

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

Se è necessario un URI di base alternativo per risolvere i riferimenti relativi nelle voci del contenuto della parte, un'applicazione deve specificare in modo esplicito l'alternativa. Determinati tipi di contenuto espongono determinati modi per specificare l'URI di base alternativo. Ad esempio, XML usa l'attributo xml:base, HTML usa l'elemento base> e Open Packaging Conventions usa l'attributo<TargetMode per gli elementi Relationship.

Usando l'URI "pack:" di una parte come URI di base per un riferimento relativo garantisce che la risorsa a cui si fa riferimento farà parte dello stesso pacchetto ([2], sezione 5.2), a meno che il riferimento relativo non si trova nel formato di percorso di rete usato raramente , ovvero un riferimento relativo a partire da "//").

Esempio: Risoluzione di un riferimento relativo

Riferimento relativo . /.. /page2.xaml all'interno della parte indirizzata come pack://http%3a,www.site.com,windows,p1.xps/pages/page1.xaml viene risolto in pack://http%3a,,www.site.com,windows,p1.xps/page2.xaml, indirizzando la parte denominata /page2.xaml.

I produttori di pacchetti possono usare nomi di parte come forma valida di riferimenti relativi. Tuttavia, quando si usano nomi di parte come riferimenti relativi, i produttori devono considerare se le parti a cui si fa riferimento possono essere risolte anche come risorse estratte all'esterno del pacchetto. Una volta estratte parti da un pacchetto, i nomi delle parti usati come riferimenti relativi potrebbero non essere risolti come previsto. La barra iniziale obbligatoria per i nomi di parte, specificata dalla grammatica del nome parte, implica che tali riferimenti relativi vengano risolti dalla radice dell'autorità corrente.

Esempio: Indirizzamento delle risorse estratte

Nel contenuto di una parte denominata /doc1/pages/page1.xaml, il riferimento relativo /page2.xaml indirizza la parte denominata /page2.xaml e il riferimento relativo ./page3.xaml indirizza la parte denominata /doc1/pages/page3.xaml.

Dopo che le parti /doc1/pages/page1.xaml, /doc1/pages/page3.xaml e /part2.xaml vengono estratte dal pacchetto ai file denominati file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml e file:///c:/mydocs/page2.xaml (rispettivamente), il riferimento relativo ./page3.xaml indirizza il file file:///c:/mydocs/doc1/pages/page3.xaml, che è previsto; tuttavia, il riferimento relativo /page2.xaml ora indirizza il file denominato file:///page2.xaml.

Riferimenti relativi nelle relazioni

Le convenzioni open packaging definiscono le connessioni tra le parti di origine e di destinazione in un pacchetto come relazioni ([1], sezione 1.3).

Le relazioni vengono raggruppate e archiviate in base alle origini. Una parte relazioni contiene relazioni che hanno origine nella stessa parte di origine. Ogni relazione viene descritta da un elemento XML all'interno del contenuto di questa parte delle relazioni. La parte relazioni è associata in modo univoco a questa parte di origine (e viceversa) usando una convenzione di denominazione definita per la parte relazioni.

L'URI di base predefinito per gli URI specificati in ogni elemento Relationship è l'URI "pack:" della parte di origine ([1], sezione 1.3.5). L'attributo TargetMode di un elemento Relationship indica l'URI di base per la relazione specificata.

Esempio: Elemento Relazione

L'elemento nella parte relazioni che definisce una relazione da una parte di origine denominata /pages/page1.xaml alla parte di destinazione /fonts/arial.ttf all'interno dello stesso pacchetto può essere simile al seguente:

<Tipo di relazione="https://schemas.microsoft.com/xps/2005/06/restricted-font"

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

Il valore Interno dell'attributo TargetMode indica che l'URI di base per l'elemento Relationship è il valore predefinito per il contenuto della parte relazioni e lo stesso dell'URI "pack:" della parte di origine relazioni. Nell'esempio precedente l'URI di base per l'elemento Relationship è l'URI "pack:" della parte /pages/page1.xaml .

Le relazioni possono anche essere destinate a risorse esterne relative alla posizione dell'intero pacchetto.

Esempio: relazione con destinazione esterna

Per un pacchetto che si trova in file:///c:/office12/sample.docx, l'elemento XML

<Id relazione="rId9"

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

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

definisce la relazione destinata al file file:///c:/office12/icon.jpg.

Il valore esterno dell'attributo TargetMode specifica che la relazione deve essere destinazione di una risorsa all'esterno del pacchetto. Se l'attributo Target contiene un riferimento relativo, è necessario un URI di base. L'URI di base per questo elemento di relazione deve essere l'URI dell'intero pacchetto.

Delega dei riferimenti alle relazioni

Alcuni formati basati su pacchetti potrebbero evitare l'uso di riferimenti URI nel contenuto, delegando riferimenti alle relazioni. Questa tecnica di delega si basa sull'uso di valori ID univoci per ogni elemento Relationship per eseguire il mapping dei riferimenti relativi nel contenuto della parte alle relazioni corrispondenti.

Esempio: Mapping di riferimenti relativi nel contenuto della parte alle relazioni

Un pacchetto che si trova in file:///c:/office12/sample.docx ha una parte denominata /word/document.xml che contiene

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

La parte relazioni associata a questa parte contiene l'elemento

<Id relazione="rId6"

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

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

Questo collega l'elemento alla parte denominata /word/media/image1.jpeg.

Il vantaggio di questo approccio è che un'applicazione può identificare e gestire tutti i riferimenti all'interno di un pacchetto, senza esaminare il contenuto nelle parti.

Tuttavia, se i riferimenti vengono delegati alle relazioni, le parti del pacchetto estratte per i file mobili potrebbero non funzionare correttamente. Per il funzionamento delle destinazioni di relazione dopo l'estrazione, un'applicazione che usa richiederà conoscenze speciali sulle relazioni, Open Packaging Conventions per la denominazione delle parti delle relazioni e la definizione degli URI di base per i file di relazione.

Supporto per la programmazione per gli URI "pack:"

Le applicazioni che producono e/o utilizzano pacchetti funzionano con indirizzi di pacchetto e parte e risolvono riferimenti relativi all'interno del contenuto delle parti. .NET Framework 3.0, che offre il set di API gestite di nuova generazione fornite da Microsoft, include classi che supportano il modello di indirizzamento delle convenzioni open packaging. Queste classi consentono alle applicazioni di comporre e analizzare i riferimenti e di ottenere le risorse del pacchetto. La classe PackUriHelper viene usata per facilitare la gestione degli URI "pack:". La classe PackWebRequest viene usata per ottenere risorse indirizzate usando gli URI "pack:".

Questa sezione illustra le funzioni eseguite da questi servizi per la composizione, l'analisi e la risoluzione dei riferimenti.

Rendere disponibili i servizi del pacchetto

È necessario installare .NET Framework versione 3.0 (o successiva) per usare le classi di servizi di creazione pacchetti. Le classi sono disponibili nello spazio dei nomi System.IO.Packaging .

Prima di usare System.Uri per le operazioni in cui sono coinvolti gli URI "pack:", lo schema URI "pack:" deve essere registrato per il dominio dell'applicazione. Il modo più semplice per registrare lo schema URI "pack:" consiste nel chiamare qualsiasi metodo della classe PackUriHelper . Lo schema può essere registrato anche senza chiamare la classe helper usando il metodo UriParser.Register , come illustrato nell'esempio seguente. Tuttavia, l'uso di questo metodo richiede autorizzazioni di sicurezza.

Esempio: Registrazione dello schema URI "pack:"

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

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

Recupero dell'URI "pack:" di una risorsa di destinazione

Quando si usa un pacchetto, l'intero pacchetto o una parte alla volta, può essere ottenuto come oggetto. In entrambi i casi, il metodo PackUriHelper.Create può essere usato per creare l'URI "pack:" del pacchetto o della risorsa parte. Questo URI "pack:" viene quindi passato al metodo PackWebRequest per ottenere la risorsa. PackWebRequest viene descritto in modo più dettagliato nella sezione successiva "Recupero delle risorse del pacchetto tramite PackWebRequest".

Un esempio comune di come le classi PackUriHelper e PackWebRequest possono essere usate per supportare l'utilizzo di un pacchetto è dettagliato nei passaggi seguenti. Se l'URI del pacchetto e l'URI della parte sono noti, un'applicazione può:

  1. Comporre un URI "pack:" dall'URI del pacchetto e dall'URI parte, usando PackUriHelper.
  2. Ottenere un flusso di bit chiamando PackWebRequest.
  3. Caricare il contenuto della parte e analizzare per ottenere riferimenti relativi.
  4. Risolvere questi riferimenti relativi rispetto all'URI di base della parte (l'URI "pack:" composto nel passaggio 1).
  5. Usare System.Uri per risolvere i riferimenti relativi e usare PackWebRequest per ottenere le risorse indicate.

Creazione di un URI "pack:" per un pacchetto desiderato

L'URI "pack:" del pacchetto può essere creato usando il metodo PackUriHelper.Create .

Esempio: 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:" creato viene passato a PackWebRequest per ottenere la risorsa del pacchetto.

Creazione di un URI "pack:" per una parte desiderata

L'URI "pack:" della parte può essere creato usando il metodo PackUriHelper.Create .

Esempio: 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:" creato viene passato a PackWebRequest per ottenere la risorsa della parte.

Risoluzione dei riferimenti relativi

Quando si elabora il contenuto di una parte, è possibile trovare riferimenti relativi che fanno riferimento ad altre parti o risorse. La risoluzione di questi riferimenti è un primo passaggio per ottenere le risorse a cui si fa riferimento.

Un riferimento relativo nel contenuto di una parte viene risolto rispetto all'URI di base di una parte all'URI "pack:" della parte di destinazione. L'URI "pack:" della parte di destinazione viene passato a PackWebRequest per ottenere la risorsa della parte dal pacchetto. Il nome di una parte di destinazione, derivato dall'URI "pack:" della parte di destinazione, può essere usato anche per ottenere una parte di destinazione, passando il nome della parte al metodo Package.GetPart .

Quando si risolvono riferimenti relativi alle parti di destinazione, esistono diversi percorsi che la risoluzione può assumere, a seconda delle informazioni disponibili all'inizio e se il pacchetto è aperto (o può essere aperto). Due di questi percorsi sono i seguenti:

  • All'inizio:

    1. L'URI "pack:" della parte contenente il riferimento è noto.
    2. Il pacchetto non è aperto.
    //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.
    
  • All'inizio:

    1. Il nome della parte contenente il riferimento è noto.
    2. Il pacchetto è aperto.
    //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);
    

Fornitura di nomi di parte alla classe package

Una volta aperto un pacchetto, la classe Package è utile per aggiungere parti ai pacchetti, ottenere parti ed eliminare parti. I metodi della classe Package , ad esempio Package.AddPart, Package.DeletePart e Package.GetPart, accettano un URI di parte come parametro. Il metodo PackUriHelper.CreatePartUri può essere utilizzato per creare un nome di parte valido da un riferimento relativo all'URI di base del pacchetto.

Esempio: 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"

Servizio per la generazione di riferimenti relativi

Un'applicazione di creazione potrebbe dover derivare un riferimento relativo che, se inserito nel contenuto di una parte di origine, punta a una parte di destinazione. Questo scopo è usato dal metodo GetRelativeUri .

Esempio: Esempio di 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"

Recupero delle risorse del pacchetto tramite PackWebRequest

Le applicazioni possono ottenere pacchetti e parti di risorse usando PackWebRequest, una classe derivata da System.Net.WebRequest. PackWebRequest restituisce una risorsa indirizzata da un URI "pack:" specificato.

In generale, l'avvio di un packWebRequest per un URI "pack:" è costituito dai passaggi seguenti:

  1. La grammatica URI "pack:" è selezionata.
  2. Il componente dell'autorità viene estratto dall'URI "pack:" e verificato se segue la grammatica per un URI assoluto.
  3. Se il componente path dell'URI "pack:" è vuoto:
  • Il flusso del pacchetto viene ottenuto per il componente dell'autorità e restituito al chiamante.

    In caso contrario, se il componente path non è vuoto:

    1. Il pacchetto aperto viene ottenuto per la risorsa identificata dal componente dell'autorità. A seconda del set CachePolicy , PackWebRequest ottiene un pacchetto aperto da PackageStore oppure crea un WebRequest interno per la risorsa del pacchetto e apre il pacchetto dal flusso del pacchetto restituito.
    2. La parte viene ottenuta usando il componente path dell'URI "pack:" come nome della parte.
    3. Il flusso della parte viene ottenuto e restituito al chiamante.

PackWebResponse.GetStream restituisce un flusso di bit che rappresenta l'intero pacchetto (flusso di pacchetto) o una singola parte in un pacchetto (un flusso di parte).

A differenza della maggior parte dei flussi WebResponse, un flusso di pacchetti è ricercabile tramite Stream.Seek. È possibile usare un flusso di pacchetti per creare un oggetto pacchetto.

Quando si opera con la risorsa pacchetto tramite un protocollo "http:", PackWebRequest supporta il caricamento progressivo delle parti, ovvero la possibilità di ottenere risorse di parte in un ordine arbitrario, senza caricare tutti i dati nel pacchetto fino ai dati della parte.

PackWebRequest offre solo funzionalità per l'utilizzo delle risorse. Non può essere usato per pubblicare o inviare dati a un server.

PackWebRequest attualmente non supporta operazioni asincrone (ad esempio BeginGetResponse) né PackWebRequest supporta i pacchetti annidati (descritti in precedenza in "Indirizzamento di parti all'interno di un pacchetto").

The PackageStore

Quando si caricano pacchetti con parti contenenti numerosi riferimenti ad altre parti, è possibile migliorare il tempo di risposta per le richieste di risorse e ridurre il traffico di rete tramite PackageStore. PackageStore è un dizionario locale dell'applicazione di riferimenti per aprire i pacchetti. Ogni pacchetto registrato in PackageStore è identificato da un valore URI della chiave.

PackageStore consente a PackWebRequest di ottenere risorse in base alle esigenze da un pacchetto, senza effettuare una richiesta server ogni volta che è necessaria un'altra risorsa da tale pacchetto.

PackageStore non viene modificato automaticamente in seguito a una chiamata a PackWebRequest. Deve essere modificato in modo esplicito. Esistono due metodi pubblici usati per aggiungere o rimuovere riferimenti per aprire i pacchetti in PackageStore: Package.AddPackage e Package.RemovePackage.

Il criterio di cache predefinito (CacheIfAvailable) impostato in PackWebRequest fa sì che la classe tenti di usare PackageStore per ottenere il pacchetto. PackWebRequest può essere costretto a ignorare il contenuto di PackageStore durante l'acquisizione delle risorse impostando i criteri della cache su BypassCache, come descritto nella sezione successiva "Criteri di cache".

Quando si ottengono i bit di un pacchetto o di una parte in base ai criteri di cache predefiniti, PackWebRequest controlla innanzitutto PackageStore per verificare se è presente un pacchetto registrato con una chiave uguale al componente dell'autorità dell'URI "pack:". Se PackageStore non contiene il pacchetto per la chiave, PackWebRequest creerà un WebRequest interno per scaricare la risorsa usando il componente autorità dell'URI "pack:".

Criteri di cache

I criteri di cache definiscono le regole usate per determinare se una richiesta di risorsa può essere compilata usando una copia memorizzata nella cache della risorsa.

Quando si usa PackWebRequest, esistono due livelli di criteri di cache che possono essere impostati in modo esplicito. È possibile impostare criteri di cache per PackWebRequest , controllando l'interazione con PackageStore. Inoltre, è possibile impostare criteri di cache per la cache controllata da un WebRequest interno. È possibile accedere a WebRequest interno tramite PackWebRequest, usando PackWebRequest.GetInternalRequest().

I criteri di cache impostati nell'oggetto WebRequest interno non avranno alcun effetto se PackWebRequest.CachePolicy è impostato su CacheOnly, causando l'ottenimento della risorsa del pacchetto da PackageStore.

PackWebRequest.CachePolicy supporta un subset di criteri, come indicato di seguito, a causa delle funzionalità specifiche di PackageStore.

Tabella 1. Criteri PackWebRequest.CachePolicy

CachePolicy Descrizione
BypassCache Ignorare le voci packageStore con un URI corrispondente.
CacheOnly Prendere in considerazione solo le voci packageStore (non creare mai un'operazione WebRequest per eseguire query sul server per i dati).
CacheIfAvailable Controllare PackageStore e usare qualsiasi pacchetto presente se ne viene trovato uno; in caso contrario, effettuare una richiesta di rete alla risorsa indicata dall'URI del pacchetto (l'URI interno dell'URI "pack:". Questo è il valore predefinito.

Per PackWebRequest, l'impostazione di tutti gli altri valori CachePolicy genera un'eccezione WebException.

Caricamento progressivo

PackWebRequest può caricare progressivamente una parte del pacchetto quando si accede al pacchetto tramite il protocollo "http:". Il caricamento progressivo consente alle applicazioni di accedere alle risorse di parte prima che l'intero pacchetto sia disponibile in locale. La funzionalità di caricamento progressivo di PackWebRequest è automatica: l'applicazione chiamante presenta prestazioni migliorate senza intervenire.

Il caricamento progressivo si basa sull'esecuzione di "richieste di intervallo di byte" per le risorse, come definito nel protocollo "http:" 1.1. Il formato di file ZIP, usato per archiviare i pacchetti in forma fisica, trae vantaggio da questo meccanismo, perché il formato di archivio ZIP mantiene informazioni importanti in una "directory centrale" alla fine fisica del file.

Dopo aver richiesto un intero pacchetto tramite PackWebRequest, il servizio inizia a restituire un flusso su cui un chiamante può cercare. Quando un pacchetto viene aperto nel flusso fornito da PackWebRequest, il chiamante può ottenere parti più rapidamente rispetto a quando si effettuano richieste dirette usando, ad esempio, il protocollo "http:".

Servizi per la valutazione e la scomposizione di URI

Identificazione dei nomi delle parti di relazione restituiti dalla classe package

Quando si gestisce una raccolta di parti ottenute utilizzando il metodo Package.GetParts , è possibile identificare le parti della relazione in modo che possano essere gestite separatamente da altre parti. PackUriHelper.IsRelationshipPartUri viene utilizzato per identificare se una parte è una parte della relazione.

Esempio: 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"

Sono disponibili altri due metodi PackUriHelper per l'uso dei nomi delle parti della relazione. PackUriHelper.GetRelationshipPartUri restituisce un nome di parte della relazione in base al nome di una parte di origine. PackUriHelper.GetSourcePartUriFromRelationshipPartUri restituisce il nome della parte di origine per un determinato nome della parte di relazione.

Confronto degli URI per l'equivalenza

Un'applicazione che usa una cache per l'archiviazione di parti durante la produzione o l'utilizzo di un pacchetto potrebbe dover eseguire controlli per i nomi di parte equivalenti. Il metodo PackUriHelper.ComparePartUri controlla l'equivalenza dei nomi di parte.

Esempio: 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"

Per determinare l'equivalenza lessicale di due URI "pack:", utilizzare il metodo PackUriHelper.ComparePackUri .

Esempio: PackUriHelper.ComparePackUri

//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"

Estrazione degli URI dei componenti da un URI "pack:"

Per estrarre l'URI del pacchetto del componente e l'URI della parte da un URI "pack:", usare rispettivamente i metodi PackUriHelper.GetPackageUri e PackUriHelper.GetPartUri.

Esempio: PackUriHelper.GetPackageUri

//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"

Esempio: Esempio di 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"

Riferimenti

Open Packaging Conventions

Uniform Resource Identifier (URI): sintassi generica

Specifica OXPS (Open XML Paper Specification)

Identificatori di risorsa internazionalizzati (IRI)