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.

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

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

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 .


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


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

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.


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.


2

HtmlInputFile-Steuerelement

Ich habe das die ganze Zeit benutzt.


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();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.