Перенаправление/просмотр представления после сгенерированного файла загружается
У меня есть действие контроллера, которое загружает динамически сгенерированный файл:
public ActionResult DownloadFile()
{
var obj = new MyClass { MyString = "Hello", MyBool = true };
var ser = new XmlSerializer(typeof(MyClass));
var stream = new MemoryStream();
ser.Serialize(stream, obj);
stream.Position = 0;
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=myfile.xml");
Response.ContentType = "application/xml";
// Write all my data
stream.WriteTo(Response.OutputStream);
Response.End();
return Content("Downloaded");
}
Только для справки:
public class MyClass
{
public string MyString { get; set; }
public int MyInt { get; set; }
}
Это работает, и файл (myfile.xml) загружен.
Однако сообщение "Скачано" не отправляется в браузер.
Аналогично, если я заменил return Content("Downloaded");
для return Redirect("www.something.com");
затем браузер перенаправляется до загрузки файла.
Как немного пре-амблема, пользовательское путешествие:
- Пользователь заполняет форму в предыдущем представлении
- Форма отправлена
- XML создается и загружается
- Пользователь перенаправляется/отображается "Загруженный" вид (так что F5 не будет повторно размещать форму)
Ответы
Ответ 1
Каждый HTTP-запрос может иметь только один ответ - вы пытаетесь проникнуть в два (файл и страницу).
Обычно, когда вы отправляете HTTP-заголовок "Content-Disposition: attachment", браузер остается на текущей странице и открывает диалог сохранения файла (или автоматически сохраняет файл в ваших загрузках).
Вам придется изменить свою стратегию, если вы хотите предотвратить повторное представление формы. Я бы предложил немного javascript, чтобы отключить кнопку отправки формы и показать сообщение "Завершено" в наложении div?
Ответ 2
Как сказал Росс, вы можете вернуть только один ответ на HTTP-запрос.
Что я делаю в этом случае:
- Отправить запрос на сервер
- Сервер создает файл и сохраняет его в некоторой структуре данных на стороне сервера (Cache, Usersession, TempData).
- Сервер возвращает
RedirectToAction()
(шаблон POST, REDIRECT, GET)
- Переадресованное действие возвращает вид с некоторым javascript, который
- Запускает загрузку предварительно сгенерированного файла, устанавливая свойство
window.location.href
на специальное действие загрузки, которое отправляет файл обратно в браузер
Ответ 3
Вот как я перенаправлен после загрузки файла.
Основной логикой является ожидание перенаправления до загрузки файла.
Для этого рассчитывается ответ на стороне сервера, а перенаправление задерживается с использованием времени ответа на сервер + смещение.
Код сервера на стороне сервера:
[HttpPost]
public ActionResult GetTemplate()
{
return Json(new {Url = Url.Action("ReturnTemplate") });
}
[HttpGet]
public ActionResult ReturnTemplate()
{
FileResult fileResult = // your file path ;
return fileResult;
}
Клиентский код:
<div id="btnGen" align="right"><button class="main-button" id="generateTemplate" type="Submit"></div>
JavaScript:
$("#generateTemplate").click(function () {
var startTime = (new Date()).getTime(), endTime;
$.ajax({
url: '@Url.Action("GetTemplate", "Controller")',
type: 'POST',
traditional: true,
dataType: "json",
contentType: "application/json",
cache: false,
data: JSON.stringify(),
success: function (result) {
endTime = (new Date()).getTime();
var serverResponseTime = endTime - startTime + 500;
setInterval(function () { Back() }, serverResponseTime);
window.location = result.Url;
}
});
});
function Back() {
window.location = '@Url.Action("Index","Controller")';
}