none
faire télécharger un fichier (TransmitFile) RRS feed

  • Question

  • Bonjour,

    j'essaye de faire télécharger un fichier en C#

    Voici le code que j'utilise :

    Extrait de code

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["FullFileName"] != null)
            {
                string fileName = Session["FullFileName"].ToString();
                FileInfo file = new FileInfo(fileName);
                Session.Contents.Remove("FullFileName");
                if (file.Exists)
                {               
                    Response.Buffer = false;
                    Response.Clear();
                    Response.ClearContent();
                    Response.ClearHeaders();
                    Response.ContentType = "application/octet-stream";
                    Response.AddHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(fileName));
                    Response.TransmitFile(fileName);
                    Response.End();
                }
            }

            throw new Exception("Invalid file request");
        }


    Ca m'ouvre bien la boîte de dialogue, et j'enregistre bien le fichier, MAIS
    le fichier que je télécharge est de taille supérieure (presque deux fois) au fichier que je vois sur le disque (si je regarde file.Length elle est bonne, mais une fois téléchargé c'est fini)

    J'ai fait l'essai sur un petit fichier texte (92 octets), le fichier téléchargé en fait 100, et quand je les édite (avec Notepad++) je vois que je premier - crée sous notepad tout court - est en ANSI, or le second me dit ANSI MAIS avec présence du BOM UTF-8
    Je ne comprends pas ce que je suis censé faire, mon code transmet en général (mais pas tout le temps) des fichiers binaires donc je me tappe a priori de l'encodage, non ??

    Enfin bref là ça fait deux heures perdues à jouer avec ContentEncoding, HeaderEnconding, WriteFile, d'autres ContentType, rien n'y fait Sad

    J'en appelle à votre bon coeur Smile


    mardi 16 octobre 2007 14:39

Réponses

  •  

    Bonjour,

     

    Voici un bout de code qui devrait répondre à votre problème ( je l'ai développé en VB, mais vous pourrez le transcoder en C# avec Reflector)

     

    Extrait de code

        ''' <summary>
        ''' Télecharge un fichier depuis le serveur Web vers le poste client.
        ''' </summary>
        ''' <param name="FilePath">Chemin d'accès absolu du fichier sur le serveur</param>
        ''' <returns>retourne True si l'opération s'est correctement déroulée.</returns>
        ''' <remarks></remarks>
        Private Function DownloadFile(ByVal FilePath As String) As Boolean

            Dim myFileStream As New System.IO.FileStream(FilePath, _
                                        System.IO.FileMode.Open, _
                                        System.IO.FileAccess.Read, _
                                        System.IO.FileShare.Read)
            Try
                If myFileStream.CanRead() Then
                    Response.Clear()
                    Response.ContentType = "application/octet-stream"

                    ' get the filename
                    Dim myFileName As String = System.IO.Path.GetFileName(FilePath)
                    Response.AddHeader("Content-Disposition", "attachment; filename=" & myFileName)

                    ' Set the buffer that will receive the data from the file
                    Dim myBuffer(4096) As Byte

                    ' Setup the Time out in seconds according to file size
                    Server.ScriptTimeout = 3600

                    While True
                        ' Check if the client is still connected
                        If Not Response.IsClientConnected Then
                            Exit While
                        End If

                        ' read data from the file
                        Dim myNumberOfBytesRead As Integer = myFileStream.Read(myBuffer, 0, 4096)
                        If myNumberOfBytesRead = 0 Then
                            Exit While
                        End If

                        ' Write the data to the current output stream.
                        Response.OutputStream.Write(myBuffer, 0, myNumberOfBytesRead)

                        ' Flush the data to the HTML output.
                        Response.Flush()

                    End While
                End If

            Catch ex As Exception
                Throw ex

            Finally
                myFileStream.Close()
                myFileStream.Dispose()
                Response.End()
            End Try

            Return True

        End Function

     

     

     

     

     

    mercredi 17 octobre 2007 10:38

Toutes les réponses

  • Bonjour,

     

    L'utilisation de la méthode TransmitFile est à bannir car elle ne permet pas un contrôle fin de ce qui est réellement envoyé.

    Je reviens vers vous dans la journée avec un exemple de code adéquat.

     

    Cordialement.

     

     

    mercredi 17 octobre 2007 07:10
  •  

    Bonjour,

     

    Voici un bout de code qui devrait répondre à votre problème ( je l'ai développé en VB, mais vous pourrez le transcoder en C# avec Reflector)

     

    Extrait de code

        ''' <summary>
        ''' Télecharge un fichier depuis le serveur Web vers le poste client.
        ''' </summary>
        ''' <param name="FilePath">Chemin d'accès absolu du fichier sur le serveur</param>
        ''' <returns>retourne True si l'opération s'est correctement déroulée.</returns>
        ''' <remarks></remarks>
        Private Function DownloadFile(ByVal FilePath As String) As Boolean

            Dim myFileStream As New System.IO.FileStream(FilePath, _
                                        System.IO.FileMode.Open, _
                                        System.IO.FileAccess.Read, _
                                        System.IO.FileShare.Read)
            Try
                If myFileStream.CanRead() Then
                    Response.Clear()
                    Response.ContentType = "application/octet-stream"

                    ' get the filename
                    Dim myFileName As String = System.IO.Path.GetFileName(FilePath)
                    Response.AddHeader("Content-Disposition", "attachment; filename=" & myFileName)

                    ' Set the buffer that will receive the data from the file
                    Dim myBuffer(4096) As Byte

                    ' Setup the Time out in seconds according to file size
                    Server.ScriptTimeout = 3600

                    While True
                        ' Check if the client is still connected
                        If Not Response.IsClientConnected Then
                            Exit While
                        End If

                        ' read data from the file
                        Dim myNumberOfBytesRead As Integer = myFileStream.Read(myBuffer, 0, 4096)
                        If myNumberOfBytesRead = 0 Then
                            Exit While
                        End If

                        ' Write the data to the current output stream.
                        Response.OutputStream.Write(myBuffer, 0, myNumberOfBytesRead)

                        ' Flush the data to the HTML output.
                        Response.Flush()

                    End While
                End If

            Catch ex As Exception
                Throw ex

            Finally
                myFileStream.Close()
                myFileStream.Dispose()
                Response.End()
            End Try

            Return True

        End Function

     

     

     

     

     

    mercredi 17 octobre 2007 10:38
  • Merci bien, ce code fonctionne.


    Cela dit, pour information, le problème venait bien d'un encodage malencontreux ajouté en fait en beginrequest dans global.asax, un collègue avait ajouté un comportement à Response.Filter qui ajoutait des données de debuggage encodées en UTF-8.
    jeudi 18 octobre 2007 13:58