5

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

2 Answers 2

3

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"; } } } 
Sign up to request clarification or add additional context in comments.

Comments

0

A more direct answer to the server-side part of the question:

public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; // *Very Important* Security checks need to go here (is the user authorised to upload.. And do we want to restrict filetypes eg. executable scripts to prevent common hacking attempts) // This can be done via prior security checks and setting a session variable as such: // if ((bool)Session["ValidatedUser"] != true) throw new Exception("Invalid Permissions"); // Check if file has been sent if (context.Request.Files.Count > 0) { // Save uploaded file HttpPostedFile uploadedFile = context.Request.Files[0]; uploadedFile.SaveAs("D:/MyUploadFolder/" + uploadedFile.FileName); context.Response.Write("OK"); } else context.Response.Write("No file attached"); } 

Obviously this can be expanded however required.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.