Использование файла Stream ASP.NET MVC FileContentResult в браузере с именем?
есть ли способ потоковой передачи файла с помощью ASP.NET MVC FileContentResult в браузере с определенным именем?
Я заметил, что вы можете иметь FileDialog (Open/Save) или вы можете передавать файл в окне браузера, но тогда он будет использовать ActionName при попытке сохранить файл.
У меня есть следующий сценарий:
byte[] contents = DocumentServiceInstance.CreateDocument(orderId, EPrintTypes.Quote);
result = File(contents, "application/pdf", String.Format("Quote{0}.pdf", orderId));
когда я использую это, я могу передавать байты, но диалог открытия / сохранения файла предоставляется пользователю. Я хотел бы на самом деле поток этот файл в окне браузера.
Если я просто использую FilePathResult, он показывает файл в окне браузера, но затем, когда я нажимаю кнопку "СОХРАНИТЬ", чтобы сохранить файл в PDF, он показывает мне имя действия как имя файла.
кто-нибудь сталкивался с этим?
6 ответов
public ActionResult Index()
{
byte[] contents = FetchPdfBytes();
return File(contents, "application/pdf", "test.pdf");
}
и для открытия PDF внутри браузера вам нужно будет установить :
public ActionResult Index()
{
byte[] contents = FetchPdfBytes();
Response.AddHeader("Content-Disposition", "inline; filename=test.pdf");
return File(contents, "application/pdf");
}
на самом деле, самый простой способ-сделать следующее...
byte[] content = your_byte[];
FileContentResult result = new FileContentResult(content, "application/octet-stream")
{
FileDownloadName = "your_file_name"
};
return result;
Это может быть полезно для любого, кто сталкивается с этой проблемой. Я наконец-то нашел решение. Оказывается, даже если мы используем inline для "content-disposition" и указываем имя файла, браузеры все равно не используют имя файла. Вместо этого браузеры пытаются интерпретировать имя файла на основе пути / URL.
вы можете прочитать дальше по этому URL: безопасно загружать файл внутри браузера с правильным именем файла
Это дало мне идею, я только что создал свой URL маршрут, который преобразует URL-адрес и заканчивает его именем файла, который я хотел дать файлу. Так, например, мой исходный вызов контроллера просто состоял из передачи идентификатора заказа печатаемого заказа. Я ожидал, что имя файла в формате{0}.pdf, где {0} - идентификатор заказа. Аналогично для кавычек я хотел Quote{0}.документ pdf.
в моем контроллере, я просто пошел вперед и добавил дополнительный параметр, чтобы принять имя файла. Я передал имя файла в качестве параметра в URL-АДРЕС.Метод действия.
затем я создал новый маршрут, который сопоставил бы этот URL-адрес с форматом: http://localhost/ShoppingCart/PrintQuote/1054/Quote1054.формат PDF
routes.MapRoute("", "{controller}/{action}/{orderId}/{fileName}",
new { controller = "ShoppingCart", action = "PrintQuote" }
, new string[] { "x.x.x.Controllers" }
);
это в значительной степени решило мою проблему. Надеюсь, это кому-то поможет!
Cheerz, Ануп!--2-->
предыдущие ответы верны: добавление линии...
Response.AddHeader("Content-Disposition", "inline; filename=[filename]");
...приведет к тому, что в браузер будет отправлено несколько заголовков Content-Disposition. Это происходит b / c FileContentResult
внутренне применяет заголовок, Если вы предоставляете ему имя файла. Альтернативным и довольно простым решением является простое создание подкласса FileContentResult
и переопределить его ExecuteResult()
метод. Вот пример, который создает экземпляр System.Net.Mime.ContentDisposition
class (тот же объект, используемый во внутреннем FileContentResult
реализация) и передает его в новый класс:
public class FileContentResultWithContentDisposition : FileContentResult
{
private const string ContentDispositionHeaderName = "Content-Disposition";
public FileContentResultWithContentDisposition(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
: base(fileContents, contentType)
{
// check for null or invalid ctor arguments
ContentDisposition = contentDisposition;
}
public ContentDisposition ContentDisposition { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
// check for null or invalid method argument
ContentDisposition.FileName = ContentDisposition.FileName ?? FileDownloadName;
var response = context.HttpContext.Response;
response.ContentType = ContentType;
response.AddHeader(ContentDispositionHeaderName, ContentDisposition.ToString());
WriteFile(response);
}
}
в своем Controller
, или в Controller
, вы можете написать простой помощник для создания экземпляра FileContentResultWithContentDisposition
а затем вызовите его из своего метода действия, например:
protected virtual FileContentResult File(byte[] fileContents, string contentType, ContentDisposition contentDisposition)
{
var result = new FileContentResultWithContentDisposition(fileContents, contentType, contentDisposition);
return result;
}
public ActionResult Report()
{
// get a reference to your document or file
// in this example the report exposes properties for
// the byte[] data and content-type of the document
var report = ...
return File(report.Data, report.ContentType, new ContentDisposition {
Inline = true,
FileName = report.FileName
});
}
теперь файл будет отправлен в браузер с выбранным вами именем файла и заголовком content-disposition "inline; filename=[filename]".
надеюсь, это поможет!
самый простой способ потоковой передачи файла в браузер с помощью ASP.NET MVC это:
public ActionResult DownloadFile() {
return File(@"c:\path\to\somefile.pdf", "application/pdf", "Your Filename.pdf");
}
Это проще, чем метод, предложенный @azarc3, так как вам даже не нужно читать байты.
кредит идет на: http://prideparrot.com/blog/archive/2012/8/uploading_and_returning_files#how_to_return_a_file_as_response
* * Edit**
по-видимому, мой "ответ" совпадает с вопросом OP. Но я не у него проблемы. Вероятно, это была проблема со старой версией ASP.NET MVC?
public FileContentResult GetImage(int productId) {
Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
if (prod != null) {
return File(prod.ImageData, prod.ImageMimeType);
} else {
return null;
}
}