Нужна помощь в отладке загрузки изображений Ajax на основе XHR с ASP.NET MVC2 - PullRequest
9 голосов
/ 13 сентября 2010

Я пытаюсь использовать скрипт, найденный из http://valums.com/ajax-upload/

Мой контроллер выглядит следующим образом

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());
        }

    }

}

И у меня есть частичное представление, подобное этому

<%@ 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>

У меня есть fileuploader.js и fileuploader.css, связанные правильно на главной странице, и загрузчик отображается правильно, и он даже вызывает мое действие, но HttpPostedFileBase имеет значение null, а действие загрузки выдает исключение.Любое понимание того, что я должен делать?

Редактировать

Итак, я выяснил, используя firebug, что он отправляет запрос XmlHttpRequest.Как мне справиться с этим в моем действии загрузки?

1 Ответ

9 голосов
/ 13 сентября 2010

Причина, по которой вы получаете пустой параметр в действии контроллера, заключается в том, что этот плагин не отправляет запрос multipart/form-data на сервер.Вместо этого он отправляет заголовок запроса application/octet-stream типа содержимого и записывает содержимое файла непосредственно в поток запросов, добавляя параметр ?qqfile к URL-адресу, содержащему имя файла.Поэтому, если вы хотите получить это на контроллере, вам нужно будет непосредственно прочитать поток:

[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();
}

Если вы выберете несколько файлов, плагин просто отправит несколько запросов на сервер, так что это будет работать.

Также, если вы хотите обрабатывать файлы, размер которых превышает int.MaxValue, вам придется читать из потока запросов порциями и записывать напрямую в выходной поток вместо загрузки всего файла в буфер памяти:

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);
    }
}

Примечание: удалите имя функции createUploader из вашего document.ready.Там должна быть анонимная функция.Вы даже можете объединить его с $(function() { ... });, который вам уже требуется для настройки модального диалога.

...