I'm attempting to use the script found from http://valums.com/ajax-upload/
My controller is as follows
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using MHNHub.Areas.ViewModels;
using MHNHub.Models;
using MHNHub.ViewModels;
namespace MHNHub.Areas.Admin.Controllers
{
[Authorize(Roles = "Administrator")]
public class ImageController : Controller
{
private MHNHubEntities _entities = new MHNHubEntities();
//
// GET: /Image/
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult ImageUploader()
{
var viewModel = new ImageViewModel()
{
Image = new Image()
};
return PartialView(viewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ImageUploader(Image image)
{
try
{
_entities.Images.AddObject(image);
_entities.SaveChanges();
return RedirectToAction("Index", "Product");
}
catch (Exception ex)
{
var viewModel = new ImageViewModel()
{
Image = image,
HasError = true,
ErrorMessage = ex.Message
};
return PartialView(viewModel);
}
}
private string _uploadsFolder = HostingEnvironment.MapPath("~/App_Data/Files");
public Guid Upload(HttpPostedFileBase fileBase)
{
var identifier = Guid.NewGuid();
fileBase.SaveAs(GetDiskLocation(identifier));
return identifier;
}
private string GetDiskLocation(Guid identifier)
{
return Path.Combine(_uploadsFolder, identifier.ToString());
}
}
}
And I have a partial view like this
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MHNHub.ViewModels.ImageViewModel>" %>
<script type="text/javascript">
$(function () {
$("#imagedialog").dialog({
bgiframe: true,
height: 170,
width: 430,
modal: true,
autoOpen: false,
resizable: true
})
});
$(document).ready(function createUploader() {
var uploader = new qq.FileUploader({
element: document.getElementById('fileuploader'),
action: '/Image/Upload/',
name: 'name'
});
});
</script>
<div id="imagedialog" title="Upload Image">
<div id="fileuploader">
</div>
<h6>Drag and drop files supported in Firefox and Google Chrome with javascript enabled.</h6>
<noscript>
<form action="/image/upload" enctype="multipart/form-data" method="post">
Select a file: <input type="file" name="photo" id="photo" />
<input type="submit" value="Upload" name="submit"/>
</form>
</noscript>
</div>
<div class="editor-field">
<img src="<%: Model.Image.FileName %>" />
<%: Html.TextBoxFor(model => model.Image.FileName) %>
<%: Html.ValidationMessageFor(model => model.Image.FileName)%>
<a href="#" onclick="jQuery('#imagedialog').dialog('open'); return false">Upload Image</a>
</div>
I have fileuploader.js and fileuploader.css linked properly on the master page, and the uploader appears correctly, and its even calling my action, but the HttpPostedFileBase is null and the upload action throws an exception. Any insight as to what I should do?
Edit
So I've figured out using firebug that its sending an XmlHttpRequest. How do I handle this in my upload action?
The reason you are getting an empty parameter in your controller action is because this plugin doesn't send a multipart/form-data
request to the server. Instead it sends application/octet-stream
content type request header and it writes the file contents directly to the request stream, appending a parameter ?qqfile
to the URL containing the file name. So if you want to retrieve this on the controller you will need to directly read the stream:
[HttpPost]
public ActionResult Upload(string qqfile)
{
using (var reader = new BinaryReader(Request.InputStream))
{
// This will contain the uploaded file data and the qqfile the name
byte[] file = reader.ReadBytes((int)Request.InputStream.Length);
}
return View();
}
If you select multiple files the plugin simply sends multiple requests to the server so this will work.
Also if you want to handle files bigger than int.MaxValue
you will have to read from the request stream in chunks and write directly to an output stream instead of loading the whole file into a memory buffer:
using (var outputStream = File.Create(qqfile))
{
const int chunkSize = 2 * 1024; // 2KB
byte[] buffer = new byte[chunkSize];
int bytesRead;
while ((bytesRead = Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
{
outputStream.Write(buffer, 0, bytesRead);
}
}
Remark: Remove the createUploader
function name from your document.ready
. It should be an anonymous function there. You could even merge it with the $(function() { ... });
you already have to setup the modal dialog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With