2

I am currently developing an application for a client that will use the administration panel for uploading images to the picture gallery and some other scanned documents to the database. I have successfully written the controller action for saving and retrieving the files saved in the database.

Now I am stuck on how to display a progress bar when the file is uploading to the database. I have tried several controls, like jQuery's uploadify and some others. They are all successful in saving the file to a folder albeit not while uploading to MS-SQL Database.

Here's a sample of my Model:

    public Class myImages
    {
       [Key, Required]
       public string ImageID { get; set; }

       [Required, MaxLength(100), DisplayName("Image Title:")]
       public string ImageTitle { get; set; }

       [DisplayName("Image File:")]
       public byte[] ImageData { get; set; }
       public string ImageContentType { get; set; }
    }

I have created a function in infrastructure for returning a byte array of the uploaded file, here's the code:

    public byte[] uploadedFileToByteArray(HttpPostedFileBase file)
    {
       int nFileLen = file.ContentLength;
       byte[] result = new byte[nFileLen];
       file.InputStream.Read(result, 0, nFileLen);
       return result;
    }

...And here's the Control Action for Create

    [HttpPost, ValidateInput(false), ValidateAntiForgeryToken]
    public ActionResult Create(myImage myimage)
    {
       if (ModelState.IsValid)
          {
             myimage.ImageID = DateTime.Now.Ticks.ToString();
             myimage.ImageData = uploadedFileToByteArray(Request.Files[0]);
             myimage.ImageContentType = Request.Files[0].ContentType;

             db.Pictures.Add(picture);
             db.SaveChanges();
             return RedirectToAction("Index");  
          }
      return View(picture);
    }

As I have said, the above code is working perfectly fine, alas I cannot seem to get the progress bar working while the file is uploading. Any ideas how to do it?

I have also tried uploading the file to a temp folder and then reading the bytes of that file, then uploading to the SQL Server, this approach works, but for some reason my client does not want that and I am also not satisfied with this solution.

I have also noticed that when uploading the file, Google's chrome shows the upload percent, if the browser can access the data at client side, is there a way to access the uploaded/sent bytes via jQuery or Ajax to display a progress bar while uploading?

I am using Visual Studio 2010, ASP.NET, MVC 3.

1 Answer 1

2

You need to read the bytes into memory in chunks, updating the amount of data read in some server-side variable (in the session, perhaps) that can be accessed by the upload plugin you are using to measure progress. As it is you read all of the data in one go and there is no way to report partial progress. Use another action to report back the amount read so far for the progress indicator. Note, you might need to use an asynchronous controller to make this work.

Note this is just for an idea. It would need quite a bit of work to be robust, handle multiple files, etc.

public byte[] uploadedFileToByteArray(HttpPostedFileBase file)
{
   int nFileLen = file.ContentLength;
   int currentPosition = 0;
   byte[] result = new byte[nFileLen];
   Session["fileLen"] = nFileLen;
   int bytesRead = file.InputStream.Read(result,0,1000);
   while (bytesRead > 0)
   {
      currentPosition += bytesRead;
      Session["progress"] = currentPosition;
      bytesRead = file.InputStream.Read(result,currentPosition,1000);
   }
   return result;
}

public ActionResult ReportProgress()
{
     int nFileLen = (int)Session["fileLen"];
     int progress = (int)Session["progress"];

     return Json( new { Progress = (float)progress/nFileLen, Complete = nFileLen >= progress } );
}
Sign up to request clarification or add additional context in comments.

5 Comments

I was actually thinking on trying AJAX with this, but the thought of reading byte chunks never came to me, i'll try it. But the AJAX partialview will read the data and another partial view will return the amount of data read? am I right?
Ajax won't work for the upload. XmlHttpRequest doesn't support it. I really think you'll need an asynchronous controller for the upload to keep from having the server bound by a long upload, coupled with Flash/Java Applet or hidden iframe technique. Whatever you use should call one action to upload and another to track progress.
While working on this code using your technique, I am thinking that IF the file is uploaded to a folder on the server, then progress bar is okay, otherwise it does not work. However, in both cases you are sending (uploading via browser) to the server, hence the client is interpreting the data as it should be, so does it really matter that the file is stored in folder or memorystream?
in both cases the bytes are read using the same control, and are sent to the server or controller for further action??
@Spitfire the only difference would be that writing to a file might cause your thread to be swapped out, allowing the progress request to be processed. That's why I suggested using an asynchronous controller, which would cause the request to be non-blocking.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.