Hochladen von Dateien in ASP.net ohne Verwendung des FileUpload-Serversteuerelements

99

Wie kann ich ein ASP.net-Webformular (v3.5) dazu bringen, eine Datei mit einem einfachen alten zu veröffentlichen <input type="file" />?

Ich bin nicht an der Verwendung des ASP.net FileUpload-Serversteuerelements interessiert.

Ronnie Overby
quelle

Antworten:

133

In Ihrem 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>

Im Code dahinter:

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)));
    }
}
Mathieu
quelle
3
@mathieu, schade, dass Ihre Variante verwendet runat="server", es ist nicht unabhängig von den Server-Sachen von ASP.NET
Secret
Was ist, wenn mehr als 1 Eingänge vorhanden sind und Sie möchten, dass separate Funktionen mit beiden Dateigruppen ausgeführt werden?
Neville Nazerane
Beim Hochladen mehrerer Dateien wird für alle Dateien derselbe Dateiname zurückgegeben, sodass die erste Datei n-mal gespeichert wird. Irgendeine Idee, wie man darüber hinwegkommt?
Sohaiby
@ Martin Überprüfen Sie dieses Code-Snippet zum Speichern mehrerer Dateien
Sohaiby
1
@ DanielJ. Es gibt keine Möglichkeit, Code-Behind nicht zu verwenden, wenn Sie anschließend etwas mit der Datei tun, dh sie in einer Datenbank speichern. Natürlich könnten Sie gerade JavaScript verwenden , um die Eingabe & Datei zu packen: var fileUploaded = document.getElementById("myFile").files[0];und Sie können sogar die Bytes mit bekommen readAsArrayBuffer: stackoverflow.com/questions/37134433/... - aber was werden Sie mit allen , die Bytes Client-Seite zu tun? Das OP möchte die ASP .NET-Steuerung und nicht die serverseitige Kommunikation insgesamt vermeiden. -1 für dich.
Vapcguy
40

Hier ist eine Lösung, ohne sich auf eine serverseitige Steuerung zu verlassen, wie es OP in der Frage beschrieben hat.

Clientseitiger HTML-Code:

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

Page Load-Methode von 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
    }
}
Aycan Yaşıt
quelle
Achten Sie auf den HTTPWebRequest-Aufruf, der den vollständigen Dateipfad in MyFile.FileName sendet. Der WebClient-Aufruf sendet nur den Dateinamen. Die HTTPWebRequest führt dazu, dass MyFile.SaveAs fehlschlägt. Nur verschwendete Stunden damit, einen Kunden zu verfolgen, der arbeitet, und einen Kunden, der nicht arbeitet.
Bob Clegg
Ich habe nur Request.Files[0]anstelle von Request.Files["UploadedFile"]und während das OP gerade ASP .NET und nicht MVC verwendet, wenn jemand dies für MVC verwenden möchte, brauchen Sie nur HttpPostedFileBaseanstelle von HttpPostedFile.
Vapcguy
23

Sie werden die festlegen müssen enctypeAttribut des formzu multipart/form-data; Anschließend können Sie über die HttpRequest.FilesSammlung auf die hochgeladene Datei zugreifen .

csgero
quelle
Mein Serverformular befand sich auf einer Masterseite und ich konnte keine mehrteiligen / Formulardaten hinzufügen (seitdem auf jeder Seite). Eine schnelle und schmutzige Problemumgehung bestand darin, der Seite ein verstecktes FileUpload-Steuerelement hinzuzufügen. WebForms fügte dann die mehrteiligen / Formulardaten automatisch hinzu. Ich musste dies tun, weil ich eine Dateieingabe mit Angular2 verwendete und kein Serversteuerelement in einer Komponentenvorlage verwenden konnte.
Jason
9

Verwenden Sie das HTML-Steuerelement mit einem Runat-Server-Attribut

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

Dann in asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

Es gibt auch einige Optionen für Dritte , die den Fortschritt anzeigen, wenn Sie interessiert sind

cgreeno
quelle
3
Das macht es wieder zu einem Server-Steuerelement. ;)
ahwm
@ahwm Die OP das ASP .NET Fileupload - Steuerelement vermeiden wollten ( <asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload>) , das anders ist als zu sagen , kein setzen runat=serverauf einem inputFeld.
Vapcguy
1
Ich verstehe das so, dass sie keine ASP.NET-Steuerelemente verwenden möchten. Welches beinhaltet die HtmlInputFileKontrolle.
Ahwm
8

Ja, Sie können dies mit der Ajax-Post-Methode erreichen. Auf der Serverseite können Sie httphandler verwenden. Daher verwenden wir keine Serversteuerelemente gemäß Ihren Anforderungen.

Mit Ajax können Sie auch den Upload-Fortschritt anzeigen.

Sie müssen die Datei als Eingabestream lesen.

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);
        }
    } 

Beispielcode

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();
                }
            }
        }
    }
Samuel Joy
quelle
2
Vielleicht sollten Sie den Hinweis hinzufügen, dass fs.close()alles andere in unlesbaren Dateien landet, da diese in IIS irgendwie offen bleiben.
Mistapink
@mistapink Wird der Dateistream nicht geschlossen, wenn die Ausführung den using-Block verlässt?
Sebi
@Sebi es scheint, als hätte es vor fast 3 Jahren nicht geklappt. Ich habe es lange nicht versucht, daher kann ich hier keine eindeutige Antwort geben. Tut mir leid.
Mistapink
4

Die Request.Files-Auflistung enthält alle Dateien, die mit Ihrem Formular hochgeladen wurden, unabhängig davon, ob sie von einem FileUpload-Steuerelement stammen oder manuell geschrieben wurden <input type="file">.

Sie können also einfach ein einfaches altes Dateieingabe-Tag in die Mitte Ihrer WebForm schreiben und dann die aus der Request.Files-Sammlung hochgeladene Datei lesen.

David
quelle
4

Wie andere antworten, ist Request.Files eine HttpFileCollection, die alle Dateien enthält, die veröffentlicht wurden. Sie müssen nur dieses Objekt nach der Datei wie folgt fragen:

Request.Files["myFile"]

Was passiert jedoch, wenn mehr als ein Eingabe-Markup mit demselben Attributnamen vorhanden ist:

Select file 1 <input type="file" name="myFiles" />
Select file 2 <input type="file" name="myFiles" />

Auf der Serverseite gibt der vorherige Code Request.Files ["myFile"] anstelle der beiden Dateien nur ein HttpPostedFile-Objekt zurück. Ich habe auf .net 4.5 eine Erweiterungsmethode namens GetMultiple gesehen, aber für frühere Versionen existiert sie nicht. Im Übrigen schlage ich die Erweiterungsmethode wie folgt vor:

public static IEnumerable<HttpPostedFile> GetMultiple(this HttpFileCollection pCollection, string pName)
{
        for (int i = 0; i < pCollection.Count; i++)
        {
            if (pCollection.GetKey(i).Equals(pName))
            {
                yield return pCollection.Get(i);
            }
        }
}

Diese Erweiterungsmethode gibt alle HttpPostedFile-Objekte zurück, die den Namen "myFiles" in der HttpFileCollection haben, falls vorhanden.

Joey O.
quelle
2

HtmlInputFile-Steuerelement

Ich habe das die ganze Zeit benutzt.

Lurker In der Tat
quelle
2
Das erfordert das Hinzufügen, runat="server"was es im Wesentlichen in ein Serversteuerelement verwandelt, das sie nicht verwenden wollten.
Ahwm
@ahwm Nein, das OP wollte das spezifische ASP .NET FileUpload-Steuerelement nicht verwenden. Das ist etwas anderes als zu sagen, dass sie im Allgemeinen kein serverseitiges Steuerelement verwenden wollten.
Vapcguy
0
//create a folder in server (~/Uploads)
 //to upload
 File.Copy(@"D:\CORREO.txt", Server.MapPath("~/Uploads/CORREO.txt"));

 //to download
             Response.ContentType = ContentType;
             Response.AppendHeader("Content-Disposition", "attachment;filename=" + Path.GetFileName("~/Uploads/CORREO.txt"));
             Response.WriteFile("~/Uploads/CORREO.txt");
             Response.End();
Jean Pierre Yenque
quelle