Zwracanie pliku do obejrzenia/pobrania w ASP.NET MVC
Napotykam problem z wysłaniem plików przechowywanych w bazie danych z powrotem do użytkownika w ASP.NET MVC. Chcę mieć widok z listą dwóch linków, jeden do przeglądania pliku i pozwalający typ MIME wysłany do przeglądarki określić, jak powinien być obsługiwany, a drugi do wymuszenia pobierania.
Jeśli zdecyduję się wyświetlić plik o nazwie SomeRandomFile.bak
i przeglądarka nie ma powiązanego programu do otwierania plików tego typu, to nie mam problemu z domyślnym zachowaniem pobierania. Jeśli jednak zdecyduję aby wyświetlić plik o nazwie SomeRandomFile.pdf
lub SomeRandomFile.jpg
chcę, aby plik po prostu się otworzył. Ale chcę również zachować link do pobierania z boku, aby móc wymusić monit o pobieranie niezależnie od typu pliku. Czy to ma sens?
Próbowałem FileStreamResult
i działa dla większości plików, jego konstruktor domyślnie nie akceptuje nazwy pliku, więc nieznanym plikom przypisuje się nazwę pliku na podstawie adresu url(który nie zna rozszerzenia, które należy podać na podstawie typu zawartości). Jeśli wymuszę nazwę pliku podając tracę możliwość bezpośredniego otwarcia pliku przez przeglądarkę i otrzymuję monit o pobranie. Czy ktoś jeszcze się z tym zetknął?
//Gives me a download prompt.
return File(document.Data, document.ContentType, document.Name);
//Opens if it is a known extension type, downloads otherwise (download has bogus name and missing extension)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType);
//Gives me a download prompt (lose the ability to open by default if known type)
return new FileStreamResult(new MemoryStream(document.Data), document.ContentType) {FileDownloadName = document.Name};
Jakieś sugestie? 8 answers
public ActionResult Download()
{
var document = ...
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = document.FileName,
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
}
Uwaga: powyższy przykładowy kod nie uwzględnia znaków międzynarodowych w nazwie pliku. Patrz RFC6266 dla odpowiedniej standaryzacji. Wierzę, że najnowsze wersje ASP.Net metoda MVC File()
i klasa ContentDispositionHeaderValue
poprawnie to ujmują. - Oskar 2016-02-25
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 00:00:19
Miałem problem z zaakceptowaną odpowiedzią ze względu na brak hintingu typu na zmiennej "document": var document = ...
więc zamieszczam to, co działało dla mnie jako alternatywa na wypadek, gdyby ktoś inny miał problemy.
public ActionResult DownloadFile()
{
string filename = "File.pdf";
string filepath = AppDomain.CurrentDomain.BaseDirectory + "/Path/To/File/" + filename;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filedata, contentType);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-23 01:18:21
To Zobacz Plik (na przykład txt):
return File("~/TextFileInRootDir.txt", MediaTypeNames.Text.Plain);
Do pobierz plik (na przykład txt):
return File("~/TextFileInRootDir.txt", MediaTypeNames.Text.Plain, "TextFile.txt");
Uwaga: Aby pobrać plik powinniśmy przekazać filedownname argument
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 16:10:14
Odpowiedź Darina Dimitrowa jest prawidłowa. Tylko dodatek:
Response.AppendHeader("Content-Disposition", cd.ToString());
może to spowodować, że przeglądarka nie wyświetli pliku, jeśli odpowiedź zawiera już nagłówek "Content-Disposition". W takim przypadku możesz użyć:
Response.Headers.Add("Content-Disposition", cd.ToString());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:50
FileVirtualPath -- > Research\Global Office Review.pdf
public virtual ActionResult GetFile()
{
return File(FileVirtualPath, "application/force-download", Path.GetFileName(FileVirtualPath));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-24 00:43:49
Uważam, że ta odpowiedź jest czystsza, (na podstawie https://stackoverflow.com/a/3007668/550975 )
public ActionResult GetAttachment(long id)
{
FileAttachment attachment;
using (var db = new TheContext())
{
attachment = db.FileAttachments.FirstOrDefault(x => x.Id == id);
}
return File(attachment.FileData, "application/force-download", Path.GetFileName(attachment.FileName));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:00
Poniższy kod zadziałał u mnie za pobranie pliku pdf z usługi API i wysłanie go do przeglądarki-mam nadzieję, że pomoże;
public async Task<FileResult> PrintPdfStatements(string fileName)
{
var fileContent = await GetFileStreamAsync(fileName);
var fileContentBytes = ((MemoryStream)fileContent).ToArray();
return File(fileContentBytes, System.Net.Mime.MediaTypeNames.Application.Pdf);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 12:38:33
Innym łatwym sposobem jest
public ActionResult GetLoadingLogo()
{
if (1 == 1)
{
return new FilePathResult(Server.MapPath("~/Content/Images/ajaxLoader_dhanlaxmi.gif"), "image/gif");
}
else
{
return new FilePathResult(Server.MapPath("~/Content/Images/add-icon.png"), "image/png");
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 05:29:31