Cet astuce vous permettra de compter le nombre de telechargement d'un pdf, zip, etc...
Avant de me lancer dans ceci, j'ai regardé ce qu'il y avait de déjà présent sur le net, et je suis tombé sur l'excellent article de Fabrice sur asp-php.net :
http://asp-php.net/tutorial/asp.net/httphandlers.php. Etant donnée qu'il fait à peu de choses près la meme chose que ce que je voulais faire, je vais juste marquer le necessaire pour comprendre comment fonctionne les handler.
Tout d'abord, ca va vous servir à quoi ? imaginons que vous voulez connaitre le nombre de personne qui telechargent un zip, pour cela il y a plusieurs solutions, soit vous faites votre propre gestionnaire de zip, dans quels cas si l'utilisateur va directement sur le zip il ne sera pas vus, soit vous mettez un handler sur les fichiers zips. A chaque fois qu'un client demandera un zip, IIS demandera a votre handler la réponse à renvoyer, c'est donc vous qui êtes chargés d'envoyer la réponse au client.
Pour cela comment faire. Tout d'abord il vous faut modifier le fichier web.config en rajoutant ces elements :
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.zip" type="Handler.ZipHandler, Handler"/>
</httpHandlers>
</system.web>
</configuration>
Une rapide explication la propriété verb sert à définir le type de requete : GET, POST ou HEAD (je n'ai pas encore trouvé d'infos sur la méthode HEAD !), l'attribut path définit les types de fichiers ciblés, ca peut etre *.zip pour tout les zips mais aussi path="count*.zip" pour les zips définit de maniere suivante countTest.zip, countSecondTest.zip, ... Enfin l'attribut type, contient deux paramètres séparés par une virgule, le premier paramètre est le nom de la classe du handler, et la deuxieme le nom de l'assembly.
Dans l'exemple j'ai crée un fichier .vb contenant en gros le code suivant
Namespace Handler
public class ZipHandler
' ...
Ce code je l'ai compilé dans le fichier handler.dll. Nous verrons plus en détails comment fonctionne cette classe dans la suite de l'article.
Malheureusement si l'on s'arrete ici, quand on appellera un fichier zip, le handler ne sera pas appellé. Pour cela il faut d'abord dire que les fichiers zip sont gérés par IIS. Voici la marche à suivre :
- Aller dans le gestionnaire de service IIS (demarrer executer %SystemRoot%\system32\inetsrv\iis.msc)
- Naviguer jusqu'au repertoire de l'application et aller dans ses propriétés.
- cliquer sur configuration dans l'onglet repertoire virtuelle, puis ajouter
- Dans le nom de l'executable, vous mettez : c:\windows\microsoft.net\framework\v1.1.4322\aspnet_isapi.dll (ou semblable)
- Valider et fermer
Maintenant a chaque fois qu'un utilisateur va demander un zip il passera pas IIS, le problème c'est que l'on a pas toujours accés à IIS, dans le cas d'un hebergement mutualisé par exemple. Heureusement IIS a pensé à nous, et nous a fournit une extension fourre tout : les .ashx. l'utilisation est la même que pour les autres. Ce que je vous propose c'est de faire le web.config de cette manière :
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.zip.ashx" type="Handler.ZipHandler, Handler"/>
</httpHandlers>
</system.web>
</configuration>
pour récuperer le nom du fichier zip, sans l'ashx, je vous propose ce bout de code suivant :
Public Class Utilities
Public Shared ReadOnly Property GetFileName(ByVal Context As System.Web.HttpContext)
Get
For Each segment As String In Context.Request.Url.Segments
If segment.ToUpper.IndexOf(".ASHX") > 0 Then
Dim rtn As String
For Each s As String In segment.Split(".")
If s.ToUpper = "ASHX" Then Return rtn.Remove(rtn.Length - 1, 1) : Exit For
rtn &= s & "."
Next
End If
Next
End Get
End Property
End Class
Maintenant examinons plus en détails notre classe ZipHandler
Pour plus de simplicité au debut de votre handler, faites les imports des classes suivantes :
Imports System.Web
Imports System.IO
Pour qu'un Handler soit valide, il faut qu'il implemente IHttpHandler, cette interface possède deux membres :
Public Class ZipHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
End Get
End Property
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
End Sub
End Class
Le boolean is Reusable est définit par MSDN comme ceci : "Obtient une valeur indiquant si une autre demande peut utiliser l'instance IHttpHandler." Merci Ms :p pour les quelques tests que j'ai réalisé je n'ai encore pas vu de difference si quelqu'un la connait, peut etre dans le cas de plusieurs demande du fichier.
Ensuite la méthode ProcessRequest, est la méthode qui va nous servir pour ecrire le retour, et aussi avoir des infos sur le client etc..
Source / Exemple :
Public Class Utilities
Public Shared ReadOnly Property GetFileName(ByVal Context As System.Web.HttpContext)
Get
For Each segment As String In Context.Request.Url.Segments
If segment.ToUpper.IndexOf(".ASHX") > 0 Then
Dim rtn As String
For Each s As String In segment.Split(".")
If s.ToUpper = "ASHX" Then Return rtn.Remove(rtn.Length - 1, 1) : Exit For
rtn &= s & "."
Next
End If
Next
End Get
End Property
End Class
Public Class ZipHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
' Par défaut je met les fichiers telechargeable dan le repertoire Files\ dans le repertoire racine de l'application
' rien ne m'empeche d'avoir une URL du genre http://localhost/TestHandler/Downloads/File.zip.ashx
' alors que le fichier physique se trouve http://localhost/TestHandler/Files/File.zip.ashx
Dim _File As String = context.Request.PhysicalApplicationPath & "Files\" & Utilities.GetFileName(context)
' Vérification de l'existence du fichier.
If New FileInfo(_File).Exists = False Then
context.Response.Write("Le fichier demandé n'existe pas")
Return
End If
' C'est ici que l'on devrait ajouter une gestion des comptes de telechargement,
' On pourrait aussi vérifier s'il est authorizé à recevoir le fichier via une variable session
' context.Session("isAuthorized")
' etc...
' On ecrit le fichier
context.Response.WriteFile(_File)
End Sub
End Class
Conclusion :
J'espere avoir été assez clair, si malgré tout ce que j'ai dit reste confus, n'hésiter par à laisser un commentaire ils sont là pour ca.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.