Edit me

Webservices d’EpiFiles


Note de GSA - 06/11/

D’importantes modifications ont été effectuées au niveau du Webservice “ManifestFile” d’EpiFiles (download et upload).

Ces modifications permettent désormais le transfert de fichiers volumineux par Webservice sans nécessiter de configuration spécifique concernant la taille limite d’une requête POST ou GET.

Néanmoins les systèmes utilisant les Webservices d’EpiFiles doivent être migrés pour utiliser ce mécanisme de chunk.

Plus de détails dans la partie Webservice “ManifestFile”


Présentation

Les Webservices d’EpiFiles se basent sur le système de Webservices du noyau Voozanoo 4 (Voir documentation Sphynx). Ils utilisent l’architecture REST.

Ils se différencient par leur URL d’accès et la méthode d’appel HTTP employée (GET, PUT, POST, DELETE).

Pour rappel l’accès aux Webservices impose une authentification, elle se fait via le nom d’utilisateur et le mot de passe communiqués dans l’url :

https://​username:password​@neonatfiles.voozanoo.net/epifiles

Note : Si le username​ ou le password​ contiennent un caractère réservé pour une Url (Ex : ​:​ ​/​ ​=​ ​?​ ​@​) il faudra encoder ces caractères selon la RFC 3986​ ( Php : Voir rawurlencode()​ ).

Cette Url :

https://foo@domain.com:xk98=bU?@neonatfiles.voozanoo.net/epifiles

Deviendra :

https://foo%40domain.com:xk98%3DbU%3F@neonatfiles.voozanoo.net/epifiles

Il y a actuellement 2 Webservices en place sur EpiFiles :

https://username:password@neonatfiles.voozanoo.net/epifiles/ws/manifest[/;id]

  • GET sans id : Liste des Manifest non archivés
  • GET avec id : Détails d’un manifest
  • PUT avec id et param “archived” : Archivage d’un manifest

https://username:password@neonatfiles.voozanoo.net/epifiles/ws/manifestfile[/;id]

  • GET sans id : Liste des ManifestFile (≈ Download d’un fichier morcelé)
  • POST : Initialisation d’un upload morcelé (création ManifestFile si 1 seul morceau)
  • PUT avec id : Upload des N autres morceaux d’un fichier (puis création ManifestFile à la fin)

Appels aux Webservices

L’idéal est de faire appel aux Webservices EpiFIles via Zend_Rest_Client (Voir documentation Sphynx de Voozanoo4).

Webservice “Manifest”

Liste des Manifests non archivés

<?php
$oClient = new
Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifest');

$oResult = $oClient->get();

La structure de la réponse XML (contenue dans $oResult->response) est : N éléments <manifest>​ contenant :

  • L’élément <id>​ : Id data du manifest
  • L’élément <comment>​ : Le commentaire laissé par l’uploader
  • L’élément <creation_date>​ : Datetime de création du manifest (YYYY-MM-DD HH:mm:ss)
  • L’élément <manifest_status>​ : Statut du manifest (1 = Partial dwl, 2 = Complete dwl)

  • L’élément <manifest_files>​ :
    • Contient N éléments <id>​ : référence l’id_data des ManifestFile liés Exemple :
<response>
	<manifest>
		<id>14</id>
		<comment>lorem ipsum</comment>
		<creation_date>2013-07-12 09:16:12</creation_date>
		<manifest_status/>
		<manifest_files>
			<id>12</id>
			<id>13</id>
		</manifest_files>
	</manifest>
	<manifest>
		<id>13</id>
		<comment>Test</comment>
		<creation_date>2013-07-11 15:47:23</creation_date>
		<manifest_status>2</manifest_status>
		<manifest_files>
			<id>11</id>
		</manifest_files>
	</manifest>
</response>

Détails d’un Manifest

<?php
$oClient = new
Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifest/');

$oResult = $oClient->get();

La structure de la réponse XML (contenue dans $oResult->response) est exactement la même que celle retournée lorsqu’on liste les Manifest non-archivés, excepté qu’il n’y a qu’un seul élément <manifest>​.

Archivage d’un Manifest

<?php
$oClient = new
Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifest/');

//Ajout du paramètre "archived" ayant pour valeur 
$oClient->archived( 1 );

$oResult = $oClient->put();

Il n’y a aucune structure de réponse XML retournée, seul l’élément <status>​ est retournée avec “success​”.

Il est possible de notifier par mail le propriétaire du manifest, ainsi que le(s) manager(s) de l’entrepôt, de l’archivage du manifest en ajoutant le paramètre notify comme sur l’exemple ci–dessous.

// Notification par mail du propriétaire et des managers de l’entrepôt
$oClient->notify( 1 );

Par ailleurs on peut ajouter un message qui sera affiché dans le corps du mail via le paramètre notify_message. Le message doit être encodé en base 64. Une partie du message (les 74 premiers caractères) seront utilisés pour définir le sujet du mail.

// Message à insérer dans le mail (optionnel)
$oClient->notify_message( base64_encode( Message à envoyer ) );

epifiles1.jpg

Webservice “ManifestFile”

Informations

L’implémentation du mécanisme de morceaux (chunks) lors du téléchargement et du dépôt de fichier impose une logique plus complexe au niveau de l’application cliente.

Téléchargement de fichier (Download)

Lors d’un téléchargement (ie : l’application cliente demande un fichier à EpiFiles) l’application cliente doit effectuer un premier appel au Webservice (en GET) pour récupérer, entre autres, le contenu d’un chunk et le nombre total de chunks composant le fichier.

Si le fichier est multi-chunk (taille du fichier > à un chunk) le client doit alors boucler sur N appels au Webservice (en GET toujours) pour récupérer tous les chunks nécessaires.

epifiles2.jpg

La reconstitution du fichier est à la charge de l’application cliente. Une classe intégrée à Voozanoo est disponible pour faciliter cette tâche : Core_Library_File_Merger​ (Voir Annexes).

Dépôt de fichier (Upload)

Lors d’un dépôt de fichier (ie : l’application cliente dépose un fichier sur EpiFiles) l’application cliente doit effectuer un premier appel au Webservice ManifestFile (en POST) afin d’initialiser le processus d’upload en communiquant le premier chunk.

Si le fichier à uploader est multi-chunk (taille du fichier > à un chunk) EpiFiles retournera un identifiant de processus afin de permettre à l’application cliente de continuer à uploader le reste du fichier. L’application cliente devra ensuite effectuer N appels au Webservice (en PUT) pour communiquer les autres chunks.

Le découpage du fichier est à la charge de l’application cliente. Une classe intégrée à Voozanoo est disponible pour faciliter cette tâche : Core_Library_File_Splitter (Voir Annexes ).

Récupération d’un ManifestFile (Téléchargement)

Premier appel

<?php
	$oClient = new
	Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifestfile/12');
	$oClient->chunk_index = 1; //Récupération du premier chunk

	$oResult = $oClient->get();
	//Récupération du nb de chunks composant le fichier
	$iTotalChunks = (int) $oResult->manifest_file->file->total_chunks;

Nièmes appels

<?php
$iChunkIndex = 2;
do
{
   $oClient->chunk_index = $iChunkIndex; //Récupération du Nième chunk

   $oResult = $oClient->get();

   //... Code de reconstitution/assemblage du fichier ...

   $iChunkIndex++;
}
while( true === $oResult->isSuccess() && $iChunkIndex <= $iTotalChunks );

A noter : Ces exemples de code ne testent pas le cas d’un retour négatif du serveur (Echec), il est à la charge du développeur de s’assurer du bon déroulement des opérations.

La structure de la réponse XML (contenue dans $oResult->response) est identique quelque soit le chunk_index demandé :

Un élément <manifest_file>​ contenant :

  • L’élément <id>​ : Id data du manifestFile
  • L’élément <id_manifest>​ : Identifiant du manifest lié à ce manifestFile
  • L’élément <purge_date>​ : Date de purge prévue (YYYY-MM-DD)
  • L’élément <downloaded_by_mg>​ : Si le fichier à déjà été téléchargé par un Manager (1) ou pas (0)
  • L’élément <file>​ : Les informations relatives au fichier lié au manifestFile, sous forme de N éléments enfants :
    • L’élément <id>​ : Identifiant du fichier (varset file)
    • L’élément <content_type>​ : Le MIME type du fichier
    • L’élément <file_hash>​ : Le hash du fichier
    • L’élément <size>​ : La taille totale du fichier (en octets)
    • L’élément <filename>​ : Le nom du fichier
    • L’élément <content>​ : Le contenu du chunk demandé, encodé en base
    • L’élément <hash>​ : Le hash du content envoyé (le chunk) en md
    • L’élément <chunk_index>​ : L’index du chunk demandé (pour rappel)
    • L’élément <total_chunks>​ : Le nombre total de chunks composant le fichier

Exemple :

<response>
	<manifest_file>
		<id>13</id>
		<id_manifest>14</id_manifest>
		<purge_date>2013-08-12</purge_date>
		<downloaded_by_mgr>0</downloaded_by_mgr>
		<file>
			<id>42</id>
			<content_type>text/plain</content_type>
			<file_hash>771f5924706521c73464341fc48afb05</file_hash>
			<size>8376158</size>
			<filename>exemple.txt</filename>
			<content>TG9yZW0gaXBzdW0gZG ... aWF0IGE=</content>
			<hash>9b7d0d6488426c33d543636e77257b2b</hash>
			<chunk_index>1</chunk_index>
			<total_chunks>8</total_chunks>
		</file>
	</manifest_file>
</response>

Création d’un ManifestFile (Dépôt)

Premier appel (Initialisation)

<?php
	$oPostClient = new
	Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifestfile');

	//Fichier devant être déposer sur EpiFiles
	$sFileFullPath = "C:/test/epiconcept.jpg";

	// ... Traitement du fichier pour le découper en morceaux ...

	//Affectation des paramètres nécessaires à l’envoi
	$oPostClient->id_repository( 23 );
	$oPostClient->comment( "Upload du fichier $sFileFullPath" );
	$oPostClient->content( base64_encode( $sFirstChunkContent ) );
	$oPostClient->hash( md5( $sFirstChunkContent ) );
	$oPostClient->total_chunks( $iTotalChunksNumber );
	$oPostClient->filename( basename( $sFileFullPath ) );

	$oPostResult = $oPostClient->post();
	//Dans le cas d’un upload multi-chunk EpiFiles communiquera un identifiant de
	processus
	$sProcessId = (string) $oPostResult->response->process_id;

A noter : Cet exemple de code ne teste pas le cas d’un retour négatif du serveur (Echec), il est à la charge du développeur de s’assurer du bon déroulement des opérations.

Liste des paramètres reconnus lors de l’appel d’Initialisation :

Paramètre Oblig. Description Exemple
id_repository Non Identifiant du groupe enfant (compartiment) de l’entrepôt ou déposer le fichier Si absent, on récupère le groupe où se trouve l’utilisateur. Attention​ le Webservice génère une erreur si plus d’un groupe a été trouvé. 23
content Oui Le contenu du chunk envoyé (encodé en Base64) 0ilCLJI+ … S+/yIEJg==
hash Oui Le hash MD5 du chunk envoyé (avant encodage Base64) 0bd349e249f440d5130f160f9269fabf
filename Oui Le nom d’origine du fichier analyses.xml
total_chunks Oui Le nb total de chunks composant le fichier 5
comment Non Commentaire à utiliser pour le Manifest Analyses du 15/07/13
content_type Non Le mime type du fichier envoyé application/xml

A noter :

  • Si le fichier est mono-chunk (total_chunks == 1) le processus d’upload s’effectuera en totalité et aucun identifiant de processus sera retourné
  • Le serveur vérifie systématiquement le hash envoyé avec celui qu’il calcule vis à vis du content fourni. Dans le cas d’un fichier mono-chunk le hash du chunk est considéré comme le hash du fichier.
  • Si le content_type est absent le système le détermine automatiquement.

Si le fichier est multi-chunk le serveur enverra en réponse le process_id à communiquer ultérieurement pour continuer l’upload.

Exemple :

<response>
<process_id>c9cf7ee85456cd274986e0e317358174</process_id>
</response>

Nième appels

<?php
$oPutClient = new
Zend_Rest_Client('https://user:pwd@neonatfiles.voozanoo.net/epifiles/ws/manifestfile/id/' . $sProcessId );

//Fichier devant être déposer sur EpiFiles
$sFileFullPath = "C:/test/epiconcept.jpg";

// ... Le traitement du fichier pour le découper en morceaux a été effectué précédemment ...

$iChunkIndex = 2;
do
{
   //Affectation des paramètres nécessaires à l’envoi
   $oPutClient->content( $sNthChunk );
   $oPutClient->hash( md5( $sNthChunk ) );
   $oPutClient->chunk_index( $iChunkIndex );
   $oPutClient->total_chunks( $iTotalChunksNumber );
   $oPutClient->file_hash( $sFileHash );

   $oPutResult = $oPutClient->put();
   $iChunkIndex++;
}
while( true === $oPutResult->isSuccess() && $iChunkIndex <= $iTotalChunksNumber );

A noter : Cet exemple de code ne teste pas le cas d’un retour négatif du serveur (Échec), il est à la charge du développeur de s’assurer du bon déroulement des opérations.

  • Lors du dépot (≈ Upload) d’un fichier les emails sont envoyés à l’Uploader et aux Managers / Downloaders comme ça le serait dans le cas d’un dépôt manuel

Tant que le fichier n’est pas uploadé en totalité le process_id est retourné tel qu’il à été transmis.

Annexes

Core_Library_File_Splitter

Cette classe est là pour faciliter le découpage d’un fichier en morceaux (chunks). Elle fournie la plupart des méthodes et informations nécessaires à la manipulation du fichier ainsi découpé.

A savoir : Cette classe ne charge pas le fichier en mémoire, ce qui permet de manipuler des gros fichiers sans risque de saturer la mémoire.

Paramètres reconnus à l’instanciation (fournis sous forme de tableau associatif clé/valeur) :

Paramètre Oblig. Type Description
FileFullPath Requis si “File” absent String Chemin complet vers le fichier à découper
File Requis si FileFullPath absent Core_Library_File Objet utilisé pour alimenté FileFullPath
ChunkSize Non (Défaut: ≈ 1Mo) Integer Taille d’un chunk en octets
Base64Handling Non (Défaut : false) Boolean GetChunk() retourne le chunk encodé en Base64

Méthodes utiles :

– GetChunk ( $iChunkIndex )​ : Retourne le chunk $iChunkIndex demandé (en base64 si Base64Handling est activé)

  • GetChunkHash()​ : Retourne le hash MD5 du chunk précédemment extrait (le chunk courant) – GetFileHash()​ : Retourne le hash MD5 du fichier intégral

Core_Library_File_Merger

Cette classe facilite la reconstitution d’un fichier en morceaux (chunks). Elle fournie la plupart des méthodes de concaténation et de vérification d’intégrité du fichier reconstitué.

Paramètres reconnus à l’instanciation (fournis sous forme de tableau associatif clé/valeur) :

Paramètre Oblig. Type Description
WorkingPath Non (Défaut : déduit depuis FileManager::CreateTmpDir()) String Chemin
MergedFilename Non (Défaut : auto-généré) String Nom du fichier reconstitué
FileHash Non (Défaut : null) String Hash du fichier intégral, utile si vous appelez CheckFileHash() en fin de processus
Base64Handling Non (Défaut : false) Boolean AddChunk() décodera le chunk en Base64 avant de le fusionner au fichier

Méthodes utiles :

  • AddChunk( $sChunkValue, $sChunkHash = null ) : Ajoute le chunk $sChunkValue au fichier reconstitué (en le décodant de sa forme Base64 si Base64Handling est activé). Si $sChunkHash est fourni effectue un contrôle d’intégrité
  • CheckFileHash() : Effectue un contrôle d’intégrité entre le fichier reconstitué et le Hash préalablement communiqué (à appeler en fin de processus uniquement)
  • GetChunkIndex() : Retourne l’index du dernier écrit (le chunk courant)
  • GetMergedFilename() : Retourne le nom du fichier de fusion (qui peut être auto-généré)
  • GetMergedFullFilePath() : Retourne le chemin complet (WorkingDirectory + Filename) vers le fichier de fusion