Trucsweb.com

Trucsweb.com

ASP

RDFFav

Forcer le téléchargement d’un fichier

Forcer le téléchargement d’un PDF au lieu de l’ouvrir dans le navigateur.download, ContentType, AddHeader, octet-streamForcer le téléchargement d’un fichier

Forcer le téléchargement d’un PDF au lieu de l’ouvrir dans le navigateur. Tout passe par l’entête HTTP qui identifie le type de chaîne que le serveur doit retourner.

Il suffit d’un clic droit sur le lien pour forcer le téléchargement, pourquoi se donner autant de mal? Parce que c’est bien plus qu’un simple téléchargement. C’est aussi intercepter une requête HTTP et utiliser les ressources du serveur avant de retourner le fichier. Et les applications sont nombreuses.

  • Protégez vos images, dans un dossier sous la racine du serveur qui autorise le téléchargement une fois connecté par exemple;
  • crypter ou décrypter vos documents avant de les télécharger;
  • compter le nombre d’ouverture d’un fichier X par un usager Y;
  • etc.

Exemple d’en-tête HTTP envoyé avec une page web par un serveur Apache.

HTTP/1.0 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Server: Apache/0.8.4
Content-Type: text/html
Content-Length: 59
Expires: Sat, 01 Jan 2000 00:59:59 GMT
Last-modified: Fri, 09 Aug 1996 14:21:40 GMT

<title>Exemple</title>
<p>Ceci est une page d’exemple.</p>

Le « ContentType »

Introduit avec le protocole HTTP 1.0, l’utilisation d’en-têtes spécifiés par le Content-Type permet non seulement de transmettre un document de type text/html comme l’exemple précédent mais aussi binaire (application/octet-stream). La plupart des types de fichier ont leurs propres types MIMES, par exemple un fichier de type application/pdf, mais les types peuvent réagir différemment selon le navigateur.

EN ASP on peut simuler ou forcer un type de contenu avec Response.ContentType. NOTE : avant IIS5 Il fallait absolument placer les instructions tout en haut de la page, avant tout autre code.

Response.ContentType = "application/octet-stream"

Différents types MIME

dim sContentType
Select Case sExtension
  Case ".asf"
    sContentType = "video/x-ms-asf"
  Case ".avi"
    sContentType = "video/avi"
  Case ".doc"
    sContentType = "application/msword"
  Case ".zip"
    sContentType = "application/zip"
  Case ".xls"
    sContentType = "application/vnd.ms-excel"
  Case ".gif"
    sContentType = "image/gif"
  Case ".jpg", "jpeg"
    sContentType = "image/jpeg"
  Case ".wav"
    sContentType = "audio/wav"
  Case ".mp3"
    sContentType = "audio/mpeg3"
  Case ".mpg", "mpeg"
    sContentType = "video/mpeg"
  Case ".rtf"
    sContentType = "application/rtf"
  Case ".htm", "html"
    sContentType = "text/html"
  Case ".asp"
    sContentType = "text/asp"
  Case ".pdf"
    sContentType = "application/pdf"
  Case Else
    sContentType = "application/octet-stream"
End Select

Response.ContentType = sContentType

Ajouter l’en-tête

On a un type de document mais il faut aussi spécifier le fichier à télécharger en ajoutant une couche à l’en-tête avec AddHeader. Attention, le fichier n’est pas encore physiquement attaché à la réponse. Il ne s’agit, encore une fois, que d’indication au navigateur, à savoir « comment traité le contenu ». Nous pourrions aussi spécifier le poids avec Content-Length. Notez en passant le délai d’exécution du script (Server.ScriptTimeout) qui ajouter 18000 secondes. :

Response.Buffer = true
Server.ScriptTimeout = 18000
// Vide le « tampon http »
Response.Clear
// Indique un nouveau type de contenu
Response.ContentType = "application/octet-stream"
// Indique un fichier à télécharger avec une suggestion de nom
Response.AddHeader "Content-Disposition", "attachment; filename=document.pdf"
... // Envoie la réponse Response.Flush

Faille de sécurité

Cette technique permet de télécharger tout document à partir d’une page web ASP. Un .exe pourra être exécuté hors contexte, un code ASP pourrait être capturé. Vous devez protéger vos fichiers, ASP entres autres, pour éviter qu’un internaute astucieux ne détourne votre script à des fins malhonnêtes. Forcer le téléchargement d’un fichier .asp par exemple permet d’ouvrir la page sans exécuter le code ASP qui sera tout simplement retourné en texte clair à l’internaute! Il faut donc s’assurer de n’accepter que les bons types de documents, essentiellement en vérifiant l’extension et surtout en limitant l’accès à un dossier. Par exemple un dossier /doc/. N’ENVOYEZ JAMAIS LE CHEMIN D’ACCÈS (PATH) VIA UNE REQUÊTE HTTP.

Une bonne pratique consiste à ouvrir le fichier au préalable à l’aide de l’objet FSO, vérifier tout d’abord que le fichier existe puis récupérer l’extension.

<%
// twFichierValide([Nom de fichier], [dossier], [extensions valide])
dim sFichier : sFichier = twFichierValide(request.querystring("f"),"/documents/doc/","pdf,doc,jpg,gif,png,xml")
if sFichier <> "" then
  // fichier accepté
else
  response.write "Erreur"
end if

function twFichierValide(sFichierTemp,sDossier,sExtensions)
  twFichierValide = ""
  if sFichierTemp <> "" then
    dim oFso : Set oFso = Server.CreateObject("Scripting.FileSystemObject")
    dim sCheminFichier : sCheminFichier = Server.MapPath(sDossier) & "\" & sFichierTemp
    if oFso.FileExists(sCheminFichier) then
      dim oFichier : Set oFichier = oFso.GetFile(sCheminFichier)
      dim sExt : sExt = oFso.GetExtensionName(sCheminFichier)
      if InStr(sExtensions,sExt) > 0 then
        twFichierValide = sCheminFichier
        exit function
      end if

      set oFichier = nothing
    end if
    set oFso = nothing
  end if
End function

%>

J’ai utilisé un simple instr pour tester l’extension. On aurait pu utiliser la méthode du « split » dans une matrice ou l’usage d’expressions régulières qui demande autant sinon plus de trouble!

Le contenu

Voilà pour l’en-tête, le fichier physique maintenant. On a donc un fichier valide avec son chemin d’accès. Il reste seulement à ouvrir le fichier dans un stream et l’afficher en binaire avec Response.BinaryWrite. Puis on « flush » le tampon http pour envoyer la réponse, c’est-à-dire les en-têtes, et le fichier en binaire. Le navigateur se bornera à traiter le fichier comme l’en-tête le suggère.

dim Stream
Set oStream = Server.CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
Response.CharSet = "UTF-8"
oStream.LoadFromFile(sFichier)
Response.BinaryWrite(oStream.Read)
Response.flush
oStream.Close
Set oStream = Nothing

Code complet : twTelechargement.asp


Il suffit de passer le nom de fichier dans la requête : twTelechargement.asp?f=monFichier.pdf

<%
Response.Buffer = true
Server.ScriptTimeout = 18000
dim sFichier : sFichier = twFichierValide(request.querystring("f"), "/documents/doc/", "pdf,doc,jpg,gif,png,xml")
if sFichier = "" then
  Response.Clear
  Response.Write("Aucun fichier!")
  Response.End
end if

function twFichierValide(sFichierTemp,sDossier,sExtensions)
  twFichierValide = ""
  if sFichierTemp <> "" then
    dim oFso : Set oFso = Server.CreateObject("Scripting.FileSystemObject")
    dim sCheminFichier : sCheminFichier = Server.MapPath(sDossier) & "\" & sFichierTemp
    if oFso.FileExists(sCheminFichier) then
      dim oFichier : Set oFichier = oFso.GetFile(sCheminFichier)
      dim sExt : sExt = oFso.GetExtensionName(sCheminFichier)
      if InStr(sExtensions,sExt) > 0 then
        Response.Clear
        Response.ContentType = "application/octet-stream"
        Response.AddHeader "Content-Disposition", "attachment; filename="&oFichier.name
        Response.AddHeader "Content-Length", oFichier.Size

        dim oStream
        Set oStream = Server.CreateObject("ADODB.Stream")
        oStream.Open
          oStream.Type = 1 // Binaire
          Response.CharSet = "UTF-8"
          oStream.LoadFromFile(sCheminFichier)
          Response.BinaryWrite(oStream.Read)
          Response.flush

        oStream.Close
        Set oStream = Nothing
        twFichierValide = sCheminFichier
        exit function
      end if
      set oFichier = nothing
    end if
    set oFso = nothing
  end if
End function
%>

Bien sûr cette technique sous-entend que vous contrôlez et avez confiance dans les fichiers déposés sur le serveur.

Limite de poids

IIS limite généralement le poids d’un téléchargement à 4 Mo. Vous pouvez modifier la préférence ou livrer le fichier par paquet. Chose très facile avec un flot binaire et notre objet « stream » (ce code est probablement compatible uniquement IIS 5 et plus) :

do while mot oStream.EOS ’ fin du flot
  response.binaryWrite oStream.read(3670016) ’ Lecture par paquet de 3670016 octets.
  response.flush
loop

, Analyste programmeurConception oznogco multimédia (https://oznogco.com), Trucsweb
Dernière mise à jour :

Commentaires

    Ajouter un commentaire
    Votre adresse de courriel ne sera pas publiée. * L'astérisque indique les champs obligatoires.
    Votre évaluation du tutoriel

    10/10 sur 1 revues.
           Visites : 11970 - Pages vues : 12209
    X

    Trucsweb.com Connexion

    Connexion

    X

    Trucsweb.com Mot de passe perdu

    Connexion

    X

    Trucsweb.com Conditions générales

    Conditions

    Responsabilité

    La responsabilité des Trucsweb.com ne pourra être engagée en cas de faits indépendants de sa volonté. Les informations mises à disposition sur ce site le sont uniquement à titre purement informatif et ne sauraient constituer en aucun cas un conseil ou une recommandation de quelque nature que ce soit.

    Aucun contrôle n'est exercé sur les références et ressources externes, l'utilisateur reconnaît que les Trucsweb.com n'assume aucune responsabilité relative à la mise à disposition de ces ressources, et ne peut être tenue responsable quant à leur contenu.

    Droit applicable et juridiction compétente

    Les règles en matière de droit, applicables aux contenus et aux transmissions de données sur et autour du site, sont déterminées par la loi canadienne. En cas de litige, n'ayant pu faire l'objet d'un accord à l'amiable, seuls les tribunaux canadien sont compétents.

    X

    Trucsweb.com Trucsweb

    X

    Trucsweb.com Glossaire

    X

    Trucsweb.com Trucsweb

    X

    Trucsweb.com Trucsweb

    Conditions

    Aucun message!

    Merci.

    X
    Aucun message!
    X

    Trucsweb.com Créer un compte

    Créer un compte

    .
    @