2011-12-23 15 views
10

Mamy kilka plików przechowywanych w bazie danych sql. W formularzu ASP.NET MVC3 wyświetlamy 2 łącza:Jak uniknąć duplikowania nagłówków treści z MVC3 FileContentResult?

Wyświetl ten plik | Pobierz ten plik

Te linki prowadzą do odpowiednich metod działania. Pobieranie działa zgodnie z oczekiwaniami - kliknięcie łącza wymusza zapisanie okna dialogowego w przeglądarce. Jednak ekran powoduje, że zduplikowane nagłówki Content-Disposition są wysyłane do przeglądarki, powodując błąd w przeglądarce Chrome i pustą stronę w Firefoksie.

[ActionName("display-file")] 
public virtual ActionResult DisplayFile (Guid fileId, string fileName) 
{ 
    var file = _repos.GetFileInfo(fileId); 
    if (file != null) 
    { 
     Response.AddHeader("Content-Disposition", 
      string.Format("inline; filename={0}", file.Name)); 
     return File(file.Content, file.MimeType, file.Name); 
    } 
} 

[ActionName("download-file")] 
public virtual ActionResult DownloadFile (Guid fileId, string fileName) 
{ 
    var file = _repos.GetFileInfo(fileId); 
    if (file != null) 
    { 
     return File(file.Content, file.MimeType, file.Name); 
    } 
} 

Oto 2 nagłówki wysyłane do przeglądarki dla działania wyświetlacza:

Content-Disposition: inline; filename=name-of-my-file.pdf 
Content-Disposition: attachment; filename="name-of-my-file.pdf" 

Próbuję zmienić moje niestandardowy nagłówek Content-Disposition zawinąć nazwę pliku w cudzysłów, ale jeszcze wysłane 2 nagłówki do przeglądarki. Próbowałem również usunąć nagłówek Content-Disposition przed dodaniem niestandardowego, ale wygląda na to, że nagłówek załącznika jest dodawany po zwróceniu wartości FileContentResult.

Ten kod był używany. Uruchomiłem test wczoraj i zauważyłem, że nie działa on już w Chrome ani Firefoksie. Może to być spowodowane aktualizacjami w przeglądarkach. IE8 i Safari nadal poprawnie otwierają plik.

Aktualizacja

Dzięki ponownie Darin, masz rację. W rzeczywistości używaliśmy tego podejścia z powodu another question you answered.

Nieco więcej informacji o tym, jak to został ostatecznie rozwiązany po naszej stronie, mamy trasę niestandardową link plików Wyświetlacz:

context.MapRoute(null, 
    "path/to/display-file-attachment/{fileId}/{fileName}", 
    new 
    { 
     area = "AreaName", 
     controller = "ControllerName", 
     action = "DisplayFile", 
    } 
); 

hiperłącza na stronie przekazuje nazwę pliku do sposobu działania poprzez parametr route, więc jest już częścią adresu URL. W związku z tym nie musieliśmy dodawać niestandardowego nagłówka treści, aby nazwa pliku była zgodna z systemem, gdy użytkownik zdecydował się go pobrać (klikając ikonę zapisu w przeglądarce PDF przeglądarki). Więc po prostu stosować to:

[ActionName("display-file")] 
public virtual ActionResult DisplayFile (Guid fileId, string fileName) 
{ 
    var file = _repos.GetFileInfo(fileId); 
    if (file != null) 
    { 
     // no custom content-disposition header, and no 3rd fileName argument 
     return File(file.Content, file.MimeType); 
    } 
} 
+0

Firefox i Chrome rzeczywiście stać się bardziej rygorystyczne w ich obsłudze nagłówków Content-Disposition. –

+0

@JulianReschke, czy mógłbyś rozwinąć postacie spoza ASCII? Nie testowaliśmy tego jeszcze ze znakami Unicode w nazwach plików. – danludwig

+0

dla nie-ASCII w nazwach plików w C-D do "pracy" we wszystkich przeglądarkach, serwery obecnie muszą wykonać podsłuchiwanie User-Agent. Zobacz http://greenbytes.de/tech/tc2231/ oraz http://greenbytes.de/tech/webdav/rfc6266.html. Mam wątpliwości, że ASP.net ma to prawo, ale chciałbym dowiedzieć się, co innego. –

Odpowiedz

24

Podczas korzystania z przeciążenia File(byte[] contents, string mimeType, string fileName)Content-Disposition nagłówek jest automatycznie dodawany do reakcji z attachment, więc nie trzeba dodawać go po raz drugi. Dla inline można użyć następującego przeciążenie File(byte[] contents, string mimeType) i ręcznie dodać Content-Disposition nagłówka:

[ActionName("display-file")] 
public virtual ActionResult DisplayFile(Guid fileId) 
{ 
    var file = _repos.GetFileInfo(fileId); 
    var cd = new ContentDisposition 
    { 
     Inline = true, 
     FileName = file.Name 
    }; 
    Response.AddHeader("Content-Disposition", cd.ToString()); 
    return File(file.Content, file.MimeType); 
} 

[ActionName("download-file")] 
public virtual ActionResult DownloadFile(Guid fileId) 
{ 
    var file = _repos.GetFileInfo(fileId); 
    return File(file.Content, file.MimeType, file.Name); 
} 
+0

Uderzyłeś mnie, miałem zamiar opublikować podobną odpowiedź. Pominięto trzeci argument fileName. Jednak w naszym przypadku nie trzeba dodawać dyspozycji treści. Po prostu 'return File (file.Content, file.MimeType)' działa, ponieważ nazwa pliku pochodzi od niestandardowej trasy. – danludwig

+0

Cóż, mam nadzieję, że framework ma słuszność w odniesieniu do znaków spoza ASCII ... –

+0

@JulianReschke, jakie znaki spoza ASCII? Ramy nie robią nic na ich temat. To zależy od Ciebie. Jeśli mówisz o znakach spoza ASCII w nazwach plików, to tak, to okropna PITA. Ale nie jest to coś, co możesz mieć nadzieję, że ramy pomogą ci. To po prostu coś, co jest różnie implementowane przez różne przeglądarki. W skrócie jest to coś, czego nie powinno się używać :-) –