98 votes

Télécharger des fichiers en ASP.net sans utiliser le contrôle de serveur FileUpload

Comment puis-je faire en sorte qu'un formulaire Web ASP.net (v3.5) affiche un fichier à l'aide d'un simple formulaire de type <input type="file" /> ?

Je ne souhaite pas utiliser le contrôle de serveur FileUpload d'ASP.net.

132voto

mathieu Points 17729

Dans votre aspx :

<form id="form1" runat="server" enctype="multipart/form-data">
 <input type="file" id="myFile" name="myFile" />
 <asp:Button runat="server" ID="btnUpload" OnClick="btnUploadClick" Text="Upload" />
</form>

Dans le code derrière :

protected void btnUploadClick(object sender, EventArgs e)
{
    HttpPostedFile file = Request.Files["myFile"];

    //check file was submitted
    if (file != null && file.ContentLength > 0)
    {
        string fname = Path.GetFileName(file.FileName);
        file.SaveAs(Server.MapPath(Path.Combine("~/App_Data/", fname)));
    }
}

3 votes

@mathieu, dommage que votre variante utilise runat="server" il n'est pas indépendant de la partie serveur d'ASP.NET.

0 votes

Que faire s'il y a plus d'une entrée et que vous voulez que des fonctions distinctes soient exécutées avec les deux ensembles de fichiers.

0 votes

En l'utilisant pour télécharger plusieurs fichiers, il renvoie le même nom de fichier pour tous les fichiers et enregistre donc le premier fichier n nombre de fois. Avez-vous une idée de la façon de surmonter ce problème ?

40voto

Aycan Yaşıt Points 827

Voici une solution qui ne repose sur aucun contrôle côté serveur, comme le décrit le PO dans sa question.

Code HTML côté client :

<form action="upload.aspx" method="post" enctype="multipart/form-data">
    <input type="file" name="UploadedFile" />
</form>

Méthode Page_Load de upload.aspx :

if(Request.Files["UploadedFile"] != null)
{
    HttpPostedFile MyFile = Request.Files["UploadedFile"];
    //Setting location to upload files
    string TargetLocation = Server.MapPath("~/Files/");
    try
    {
        if (MyFile.ContentLength > 0)
        {
            //Determining file name. You can format it as you wish.
            string FileName = MyFile.FileName;
            //Determining file size.
            int FileSize = MyFile.ContentLength;
            //Creating a byte array corresponding to file size.
            byte[] FileByteArray = new byte[FileSize];
            //Posted file is being pushed into byte array.
            MyFile.InputStream.Read(FileByteArray, 0, FileSize);
            //Uploading properly formatted file to server.
            MyFile.SaveAs(TargetLocation + FileName);
        }
    }
    catch(Exception BlueScreen)
    {
        //Handle errors
    }
}

0 votes

Attention à l'appel HTTPWebRequest qui envoie le chemin complet du fichier dans MyFile.FileName. L'appel WebClient n'envoie que le nom du fichier. L'appel HTTPWebRequest entraînera l'échec de MyFile.SaveAs. J'ai perdu des heures à chercher un client qui fonctionne et un autre qui ne fonctionne pas.

0 votes

J'ai juste utilisé Request.Files[0] au lieu de Request.Files["UploadedFile"] et bien que l'OP utilisait directement ASP.NET et non MVC, si quelqu'un veut l'utiliser pour MVC, il faut simplement HttpPostedFileBase au lieu de HttpPostedFile .

23voto

csgero Points 2061

Vous devrez définir le enctype de l'attribut form a multipart/form-data ; vous pouvez alors accéder au fichier téléchargé en utilisant la commande HttpRequest.Files collection.

0 votes

Le formulaire de mon serveur se trouvait sur une page principale et je ne pouvais pas ajouter le format multipart/form-data (car il serait alors présent sur toutes les pages). Une solution de contournement rapide a été d'ajouter un contrôle FileUpload caché à la page. WebForms a alors ajouté automatiquement les données multipart/form-data. J'ai dû procéder ainsi parce que j'utilisais une entrée de fichier avec Angular2 et que je ne pouvais pas utiliser un contrôle de serveur dans un modèle de composant.

9voto

cgreeno Points 17379

Utiliser le contrôle HTML avec un attribut de serveur runat

 <input id="FileInput" runat="server" type="file" />

Puis dans asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

Il y a aussi des 3ème partie des options qui montrent les progrès réalisés si vous êtes intéressés

3 votes

Encore une fois, cela revient à en faire un contrôle de serveur ;)

0 votes

@ahwm L'OP voulait éviter le contrôle ASP.NET FileUpload ( <asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload> ) C'est différent que de dire de ne pas mettre un runat=server sur un input champ.

1 votes

J'en déduis qu'ils ne veulent pas utiliser les contrôles ASP.NET. Ce qui inclut les HtmlInputFile contrôle.

8voto

Samuel Joy Points 38

Oui, vous pouvez réaliser ceci par la méthode ajax post. Du côté du serveur, vous pouvez utiliser httphandler. Donc, nous n'utilisons pas de contrôles de serveur comme vous l'avez demandé.

avec ajax vous pouvez aussi montrer la progression du téléchargement.

vous devrez lire le fichier comme un flux d'entrée.

using (FileStream fs = File.Create("D:\\_Workarea\\" + fileName))
    {
        Byte[] buffer = new Byte[32 * 1024];
        int read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        while (read > 0)
        {
            fs.Write(buffer, 0, read);
            read = context.Request.GetBufferlessInputStream().Read(buffer, 0, buffer.Length);
        }
    } 

Exemple de code

function sendFile(file) {              
        debugger;
        $.ajax({
            url: 'handler/FileUploader.ashx?FileName=' + file.name, //server script to process data
            type: 'POST',
            xhr: function () {
                myXhr = $.ajaxSettings.xhr();
                if (myXhr.upload) {
                    myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
                }
                return myXhr;
            },
            success: function (result) {                    
                //On success if you want to perform some tasks.
            },
            data: file,
            cache: false,
            contentType: false,
            processData: false
        });
        function progressHandlingFunction(e) {
            if (e.lengthComputable) {
                var s = parseInt((e.loaded / e.total) * 100);
                $("#progress" + currFile).text(s + "%");
                $("#progbarWidth" + currFile).width(s + "%");
                if (s == 100) {
                    triggerNextFileUpload();
                }
            }
        }
    }

2 votes

Vous devriez peut-être ajouter l'indication d'ajouter un fs.close() tout le reste pourrait se retrouver dans des fichiers illisibles puisqu'ils restent en quelque sorte ouverts dans IIS.

0 votes

@mistapink Le flux de fichiers n'est-il pas fermé lorsque l'exécution quitte le bloc using ?

0 votes

@Sebi il semble qu'il y a presque 3 ans ce n'était pas le cas. Je ne l'ai pas essayé depuis longtemps, donc je ne peux pas donner une réponse définitive ici. Je suis désolé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X