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.
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)));
}
}
runat="server", it isn't independent from the server stuff of ASP.NETvar fileUploaded = document.getElementById("myFile").files[0]; and you can even get the bytes using readAsArrayBuffer: stackoverflow.com/questions/37134433/… - 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.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
}
}
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.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.
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
<asp:FileUpload ID="fileUpload1" runat="server"></asp:FileUpload>) That is different than saying to not put a runat=server on an input field.HtmlInputFile control.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();
}
}
}
}
fs.close() everything else might end up in unreadable files since they stay somehow open within IIS.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.
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.
I've used this all the time.
runat="server" which essentially turns it into a server control, which they didn't want to use.//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();