I'm trying to upload a big file to Generic Handler FileUpload.ashx.
I checked it with Fiddler data reaches to the server in correct way. But I couldn't succeed on serverside.
I tried many ways but I couldn't get the data stored in HttpContext.
I tried the old
context.Request.Files[0];
context.Request.Params["file"]
context.Request["file"];
and some other things and now im quite confused. In simple HTML only set the type file and take the input with first method above, is it complicated here? Do I have to write my own parser for the content. Isn't there a simpler way?
public void ProcessRequest(HttpContext context)
{
// what to do here
}
Can anyone provide sample for both client and server sides
By the way my client is WinRt and server side is .Net 4.5
You may want to check how they do it in this project:
https://github.com/maxpavlov/jQuery-File-Upload.MVC3
Here is the main code that handles the receiving of the uploaded file:
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
namespace jQuery_File_Upload.MVC3.Upload
{
/// <summary>
/// Summary description for UploadHandler
/// </summary>
public class UploadHandler : IHttpHandler
{
private readonly JavaScriptSerializer js;
private string StorageRoot
{
get { return Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/Files/")); } //Path should! always end with '/'
}
public UploadHandler()
{
js = new JavaScriptSerializer();
js.MaxJsonLength = 41943040;
}
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
context.Response.AddHeader("Pragma", "no-cache");
context.Response.AddHeader("Cache-Control", "private, no-cache");
HandleMethod(context);
}
// Handle request based on method
private void HandleMethod(HttpContext context)
{
switch (context.Request.HttpMethod)
{
case "HEAD":
case "GET":
if (GivenFilename(context)) DeliverFile(context);
else ListCurrentFiles(context);
break;
case "POST":
case "PUT":
UploadFile(context);
break;
case "DELETE":
DeleteFile(context);
break;
case "OPTIONS":
ReturnOptions(context);
break;
default:
context.Response.ClearHeaders();
context.Response.StatusCode = 405;
break;
}
}
private static void ReturnOptions(HttpContext context)
{
context.Response.AddHeader("Allow", "DELETE,GET,HEAD,POST,PUT,OPTIONS");
context.Response.StatusCode = 200;
}
// Delete file from the server
private void DeleteFile(HttpContext context)
{
var filePath = StorageRoot + context.Request["f"];
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
// Upload file to the server
private void UploadFile(HttpContext context)
{
var statuses = new List<FilesStatus>();
var headers = context.Request.Headers;
if (string.IsNullOrEmpty(headers["X-File-Name"]))
{
UploadWholeFile(context, statuses);
}
else
{
UploadPartialFile(headers["X-File-Name"], context, statuses);
}
WriteJsonIframeSafe(context, statuses);
}
// Upload partial file
private void UploadPartialFile(string fileName, HttpContext context, List<FilesStatus> statuses)
{
if (context.Request.Files.Count != 1) throw new HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request");
var inputStream = context.Request.Files[0].InputStream;
var fullName = StorageRoot + Path.GetFileName(fileName);
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write))
{
var buffer = new byte[1024];
var l = inputStream.Read(buffer, 0, 1024);
while (l > 0)
{
fs.Write(buffer, 0, l);
l = inputStream.Read(buffer, 0, 1024);
}
fs.Flush();
fs.Close();
}
statuses.Add(new FilesStatus(new FileInfo(fullName)));
}
// Upload entire file
private void UploadWholeFile(HttpContext context, List<FilesStatus> statuses)
{
for (int i = 0; i < context.Request.Files.Count; i++)
{
var file = context.Request.Files[i];
var fullPath = StorageRoot + Path.GetFileName(file.FileName);
file.SaveAs(fullPath);
string fullName = Path.GetFileName(file.FileName);
statuses.Add(new FilesStatus(fullName, file.ContentLength, fullPath));
}
}
private void WriteJsonIframeSafe(HttpContext context, List<FilesStatus> statuses)
{
context.Response.AddHeader("Vary", "Accept");
try
{
if (context.Request["HTTP_ACCEPT"].Contains("application/json"))
context.Response.ContentType = "application/json";
else
context.Response.ContentType = "text/plain";
}
catch
{
context.Response.ContentType = "text/plain";
}
var jsonObj = js.Serialize(statuses.ToArray());
context.Response.Write(jsonObj);
}
private static bool GivenFilename(HttpContext context)
{
return !string.IsNullOrEmpty(context.Request["f"]);
}
private void DeliverFile(HttpContext context)
{
var filename = context.Request["f"];
var filePath = StorageRoot + filename;
if (File.Exists(filePath))
{
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
context.Response.ContentType = "application/octet-stream";
context.Response.ClearContent();
context.Response.WriteFile(filePath);
}
else
context.Response.StatusCode = 404;
}
private void ListCurrentFiles(HttpContext context)
{
var files =
new DirectoryInfo(StorageRoot)
.GetFiles("*", SearchOption.TopDirectoryOnly)
.Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
.Select(f => new FilesStatus(f))
.ToArray();
string jsonObj = js.Serialize(files);
context.Response.AddHeader("Content-Disposition", "inline; filename=\"files.json\"");
context.Response.Write(jsonObj);
context.Response.ContentType = "application/json";
}
}
}