2011-12-23 55 views
10

Chúng tôi có một số tệp được lưu trữ trong cơ sở dữ liệu sql. Trên một mẫu ASP.NET MVC3, chúng tôi hiển thị 2 liên kết:Làm cách nào để tránh tiêu đề trùng lặp nội dung trùng lặp với MVC3 FileContentResult?

Xem tập tin này | Tải xuống tệp này

Các liên kết này đi đến các phương pháp hành động tương ứng này. Quá trình tải xuống hoạt động như mong đợi - việc nhấp vào liên kết sẽ buộc hộp thoại lưu trong trình duyệt. Tuy nhiên, màn hình hiển thị sẽ khiến các tiêu đề trùng lặp Content-Disposition được gửi tới trình duyệt, dẫn đến lỗi trên Chrome và một trang trống trong Firefox.

[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); 
    } 
} 

Sau đây là 2 tiêu đề gửi đến trình duyệt cho hành động hiển thị:

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

Tôi đã cố gắng thay đổi tiêu đề nội dung bố trí tùy chỉnh của tôi để bọc các tên tập tin trong dấu ngoặc kép, nhưng nó vẫn gửi 2 tiêu đề cho trình duyệt. Tôi cũng đã cố gắng loại bỏ tiêu đề Content-Disposition trước khi thêm phần tùy chỉnh, nhưng nó xuất hiện phần đầu đính kèm đang được thêm sau khi FileContentResult được trả về.

Mã này được sử dụng để hoạt động. Tôi đã chạy thử nghiệm ngay hôm qua và nhận thấy nó không còn hoạt động trong Chrome hoặc Firefox nữa. Điều này có thể là do các bản cập nhật trong trình duyệt. IE8 và Safari vẫn mở tệp một cách chính xác.

Cập nhật

Cảm ơn một lần nữa Darin, bạn là chính xác. Chúng tôi thực sự đã sử dụng phương pháp này vì another question you answered.

Một chút thông tin thêm về cách này sau cùng đã được giải quyết trên cuối của chúng tôi, chúng tôi có một lộ trình tùy chỉnh cho các liên kết tập tin hiển thị:

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

Các siêu liên kết trên trang trôi qua tên tập tin với phương pháp hành động thông qua thông số tuyến đường, do đó, nó đã là một phần của URL. Do đó, chúng tôi không cần phải thêm tiêu đề tùy chỉnh bố cục nội dung để làm cho tên tệp phù hợp với hệ thống khi người dùng quyết định tải xuống (bằng cách nhấp vào biểu tượng lưu trong trình xem PDF của trình duyệt). Vì vậy, chúng tôi chỉ sử dụng này:

[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 và Chrome đã thực sự trở thành khắt khe hơn trong việc xử lý của họ về header Content-Disposition. –

+0

@JulianReschke, bạn vui lòng xây dựng trên các ký tự không phải ASCII? Chúng tôi chưa thử nghiệm tính năng này với các ký tự unicode trong tên tệp. – danludwig

+0

đối với không phải ASCII trong tên tệp trong C-D để "hoạt động" trong tất cả các trình duyệt, máy chủ hiện cần phải thực hiện Tác nhân người dùng đánh hơi. Xem http://greenbytes.de/tech/tc2231/ và http://greenbytes.de/tech/webdav/rfc6266.html. Tôi có nghi ngờ rằng ASP.net có quyền này, nhưng tôi rất muốn tìm ra cách khác. –

Trả lời

24

Khi bạn sử dụng quá tải File(byte[] contents, string mimeType, string fileName) một tiêu đề Content-Disposition được tự động thêm vào phản ứng với attachment, vì vậy bạn không cần phải thêm nó một lần thứ hai. Đối với inline bạn có thể sử dụng quá tải sau File(byte[] contents, string mimeType) và tự thêm các Content-Disposition tiêu đề:

[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

Bạn đánh tôi với nó, tôi chuẩn bị đăng một câu trả lời tương tự. Omiting đối số 3rd fileName hoạt động. Tuy nhiên, việc bố trí nội dung không cần phải được thêm vào trong trường hợp của chúng tôi. Chỉ đơn giản là 'return File (file.Content, file.MimeType);' hoạt động, vì tên tệp được bắt nguồn từ một tuyến tùy chỉnh. – danludwig

+0

Vâng, hy vọng khung làm việc phù hợp với các ký tự không phải ASCII ... –

+0

@JulianReschke, ký tự không phải ASCII nào? Khung làm việc không có gì về chúng. Tuỳ bạn. Nếu bạn đang nói về các ký tự không phải ASCII trong tên tập tin, thì có, đó là PITA khủng khiếp. Nhưng nó không phải là một cái gì đó mà bạn có thể hy vọng khuôn khổ để giúp bạn. Nó chỉ là một cái gì đó khác nhau được thực hiện bởi các trình duyệt khác nhau. Trong ngắn hạn nó là cái gì đó không nên được sử dụng :-) –

Các vấn đề liên quan