расположение содержимого не вызывает сохранение как - PullRequest
4 голосов
/ 11 января 2012

У меня есть следующий код:

Response.ClearContent();
Response.AddHeader( "Content-type", "application/vnd.ms-excel");
Response.AddHeader("content-disposition", "attachment;filename=test.xls");
Response.ContentType = "application/excel";
var swr = new StringWriter();
var tw = new HtmlTextWriter(swr);
grd.RenderControl(tw);
Response.Write(swr.ToString());
Response.Flush();
Response.End();
tw.Close();
swr.Close();

Это действие запускается из следующего бита кода jquery:

   <img src="../../../../Content/images/Excel-icon.png" 
      onclick = "alert ($('#Filter').serialize());
                    $.ajax({
                         type: 'POST',
                         url: '<%=Url.Action( "Excel") %>',
                         data: $('#Filter').serialize(),
                         success : function (data, textStatus, jqXHR) 
                              { alert (data);},
                         error: function (jqXHR, textStatus, errorThrown)
                              { alert (textStatus + ' ' + errorThrown);}
                         });" />

Я подтвердил с помощью fiddler, что заголовки имеют ожидаемые значения. Я также вижу данные в фиддлере, используя веб-представление.

Кроме того, когда я показываю содержимое данных из функции успеха, он имеет необработанный HTML-код для таблицы, которую я пытаюсь экспортировать в Excel.

Заранее спасибо за помощь.

Ответы [ 2 ]

5 голосов
/ 11 января 2012

О нет, вы не можете использовать AJAX для загрузки файлов. Вызов AJAX выполняется, файл передается клиенту, ваш успешный обратный вызов выполняется и передается содержимое файла, в котором вы застряли. По очевидным причинам безопасности вы не можете сделать много с этими данными. Вы не можете сохранить его на клиентском компьютере. На этом этапе вы не можете отобразить подсказку «Сохранить как».

Так что удалите ваш JavaScript-вызов AJAX и вызовите действие вашего контроллера, используя обычный запрос GET или POST.

3 голосов
/ 11 января 2012

Я бы предложил не помещать этот код непосредственно в метод Action - это не очень чистый способ использования MVC, и вы, конечно, не можете инициировать загрузку файла из запроса AJAX.

Вы можете получить новый результат действия - вызвать его ExcelResult - из класса FileResult, переопределить его ExecuteResult методом, чтобы принудительно вставить содержимое в Response.

Нажатие кнопки должно просто нажать на действие по ссылке (перейдите к ней). Ответ от сервера и браузера будет работать вместе, чтобы принудительно передать файл пользователю без перехода на новую страницу.

Пример:

public class ExcelResult : FileResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        string file;

        using (var swr = new StringWriter())
        {
            using (var tw = new HtmlTextWriter(swr))
            {
                // Not sure where your grd object comes from
                grd.RenderControl(tw);
                file = swr.ToString();
            }
        }

        var response = context.HttpContext.Response;

        response.Buffer = true;
        response.Clear();
        response.ClearHeaders();
        response.ContentType = "application/excel";
        response.CacheControl = "public";
        response.AddHeader("Pragma", "Public");
        response.AddHeader("Expires", "0");
        response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
        response.AddHeader("Content-Description", "describe your file");
        response.AddHeader("Content-Disposition","attachment; filename=excel.xls");
        response.Write(file);
        response.Flush();
        response.End();
    }

}

А ваше Действие просто:

public ExcelResult Excel()
{
    return new ExcelResult(/* whatever you need to pass */);
}
...