99

How can I get an ASP.net web form (v3.5) to post a file using a plain old <input type="file" />?

I am not interested in using the ASP.net FileUpload server control.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346

9 Answers9

134

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

In code behind :

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)));
    }
}
Caius Jard
  • 72,509
  • 5
  • 49
  • 80
mathieu
  • 30,974
  • 4
  • 64
  • 90
  • 3
    @mathieu, pity that you variant does use `runat="server"`, it isn't independent from the server stuff of ASP.NET – Secret Apr 11 '13 at 14:09
  • what if there are more than 1 inputs and you want separate functions performed with both sets of files. – Neville Nazerane Jun 11 '14 at 11:01
  • while using it to upload multiple files, it returns same file name for all files and hence save the first file n number of times. Any idea how to get over it? – sohaiby Apr 29 '15 at 09:12
  • @Martina Check [this code snippet](https://gist.github.com/sohaiby/1923e120b5a12f4a62bd4c04a200c5cb) for saving multiple files – sohaiby Jan 28 '17 at 05:20
  • Ronnie wants to know a way to upload the file without using MS controls. Your example uses code behind, which is more of the same he wants to avoid -1. – Daniel J. Aug 11 '17 at 14:17
  • 1
    @DanielJ. There is no possible way to *not* use code-behind if you're going to be doing anything with the file afterwards, i.e. storing it in a database. Sure, you could use straight JavaScript to grab the input & file: `var fileUploaded = document.getElementById("myFile").files[0];` and you can even get the bytes using `readAsArrayBuffer`: https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679 - but what are you going to do with all those bytes client-side? The OP wants to avoid the ASP .NET control-not server-side communication altogether. -1 to you. – vapcguy Aug 22 '18 at 21:19
  • There are many ways to get a stream of bytes from an HTML5 browser to a server. You do not need code behind, a simple .aspx web page will do it. The thing here is whether you fall in the trap of considering that the so called "code behind" modules, are a fundamental conceptual element in regards to how a web server (IIS) processes information, or you open your eyes and realize it's just part of the Microsoft business, which basically consists in wrapping things up in a new layer and offering you different mechanisms to get the same results. – Daniel J. Aug 23 '18 at 18:48
41

Here is a solution without relying on any server-side control, just like OP has described in the question.

Client side HTML code:

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

Page_Load method of 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
  • 2,106
  • 4
  • 34
  • 40
  • Watch out for HTTPWebRequest call sending full file path in MyFile.FileName. WebClient call just sends file name. The HTTPWebRequest will cause the MyFile.SaveAs to fail. Just wasted hours chasing one client working and one client not. – Bob Clegg Nov 23 '16 at 23:12
  • I just used `Request.Files[0]` instead of `Request.Files["UploadedFile"]` and while the OP was using straight ASP .NET and not MVC, if anyone wants to use this for MVC, you just need `HttpPostedFileBase` instead of `HttpPostedFile`. – vapcguy Aug 23 '18 at 18:47
23

You'll have to set the enctype attribute of the form to multipart/form-data; then you can access the uploaded file using the HttpRequest.Files collection.

Majid
  • 13,853
  • 15
  • 77
  • 113
csgero
  • 2,753
  • 17
  • 15
  • My server form was on a master page and I could not add multipart/form-data (since then it would be on every page). A quick-and-dirty workaround was to add a hidden FileUpload control to the page. WebForms then added the multipart/form-data automatically. I had to do this because I was using a file input with Angular2 and couldn't use a server control in a component template. – Jason Dec 16 '16 at 20:04
9

use the HTML control with a runat server attribute

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

Then in asp.net Codebehind

 FileInput.PostedFile.SaveAs("DestinationPath");

There are also some 3'rd party options that will show progress if you intrested

cgreeno
  • 31,943
  • 7
  • 66
  • 87
  • 3
    Again, that's turning it into a server control. ;) – ahwm Sep 03 '13 at 18:16
  • @ahwm The OP wanted to avoid the ASP .NET FileUpload control (``) That is different than saying to not put a `runat=server` on an `input` field. – vapcguy Aug 22 '18 at 21:27
  • 1
    I take that to mean they don't want to use ASP.NET controls. Which includes the `HtmlInputFile` control. – ahwm Aug 22 '18 at 21:55
8

Yes you can achive this by ajax post method. on server side you can use httphandler. So we are not using any server controls as per your requirement.

with ajax you can show the upload progress also.

you will have to read the file as a inputstream.

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

Sample 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();
                }
            }
        }
    }
Undo
  • 25,519
  • 37
  • 106
  • 129
Samuel Joy
  • 578
  • 5
  • 8
  • 2
    Maybe you should add the hint to add an ```fs.close()``` everything else might end up in unreadable files since they stay somehow open within IIS. – mistapink Aug 22 '16 at 11:45
  • @mistapink Is the file stream not closed when the execution leaves the using block? – Sebi Apr 05 '19 at 08:33
  • @Sebi it seems like almost 3 years ago it didn't. Didn't try it for a long time, so I can not give a definite answer here. I am sorry. – mistapink Apr 26 '19 at 07:11
4

As others has answer, the Request.Files is an HttpFileCollection that contains all the files that were posted, you only need to ask that object for the file like this:

Request.Files["myFile"]

But what happen when there are more than one input mark-up with the same attribute name:

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

On the server side the previous code Request.Files["myFile"] only return one HttpPostedFile object instead of the two files. I have seen on .net 4.5 an extension method called GetMultiple but for prevoious versions it doesn't exists, for that matter i propose the extension method as:

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

This extension method will return all the HttpPostedFile objects that have the name "myFiles" in the HttpFileCollection if any exists.

Joey O
  • 41
  • 1
4

The Request.Files collection contains any files uploaded with your form, regardless of whether they came from a FileUpload control or a manually written <input type="file">.

So you can just write a plain old file input tag in the middle of your WebForm, and then read the file uploaded from the Request.Files collection.

David
  • 24,700
  • 8
  • 63
  • 83
2

HtmlInputFile control

I've used this all the time.

Lurker Indeed
  • 1,521
  • 1
  • 12
  • 21
  • 2
    That requires adding `runat="server"` which essentially turns it into a server control, which they didn't want to use. – ahwm Sep 03 '13 at 18:10
  • @ahwm No, the OP didn't want to use the specific ASP .NET FileUpload control. That is different than saying they didn't want to use a server-side control, in general. – vapcguy Aug 22 '18 at 21:29
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();
kRiZ
  • 2,320
  • 4
  • 28
  • 39