ฉันประสบปัญหาในการส่งไฟล์ที่เก็บไว้ในฐานข้อมูลกลับไปยังผู้ใช้ใน ASP.NET MVC สิ่งที่ฉันต้องการคือมุมมองที่แสดงรายการลิงก์สองรายการลิงก์หนึ่งเพื่อดูไฟล์และปล่อยให้ mimetype ที่ส่งไปยังเบราว์เซอร์พิจารณาว่าควรจัดการอย่างไรและอีกลิงค์บังคับให้ดาวน์โหลด
หากฉันเลือกที่จะดูไฟล์ที่เรียกว่าSomeRandomFile.bak
และเบราว์เซอร์ไม่มีโปรแกรมที่เกี่ยวข้องในการเปิดไฟล์ประเภทนี้แสดงว่าฉันไม่มีปัญหากับการเริ่มต้นกับพฤติกรรมการดาวน์โหลด อย่างไรก็ตามถ้าฉันเลือกที่จะดูไฟล์ที่เรียกว่าSomeRandomFile.pdf
หรือSomeRandomFile.jpg
ฉันต้องการให้เปิดไฟล์ แต่ฉันต้องการเก็บลิงค์ดาวน์โหลดไว้ด้านข้างเพื่อให้ฉันสามารถบังคับให้พรอมต์ดาวน์โหลดโดยไม่คำนึงถึงประเภทไฟล์ มันสมเหตุสมผลหรือไม่
ฉันเหนื่อย FileStreamResult
แล้วมันใช้งานได้กับไฟล์ส่วนใหญ่คอนสตรัคเตอร์ไม่ยอมรับชื่อไฟล์ตามค่าเริ่มต้นดังนั้นไฟล์ที่ไม่รู้จักจะถูกกำหนดชื่อไฟล์ตาม URL (ซึ่งไม่ทราบว่าจะให้นามสกุลตามประเภทเนื้อหา) หากฉันบังคับชื่อไฟล์ด้วยการระบุฉันจะเสียความสามารถของเบราว์เซอร์ในการเปิดไฟล์โดยตรงและฉันได้รับพรอมต์ดาวน์โหลด มีคนอื่นพบสิ่งนี้หรือไม่?
นี่คือตัวอย่างของสิ่งที่ฉันได้ลองมา
//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};
ข้อเสนอแนะใด ๆ
UPDATE:
คำถามนี้ดูเหมือนจะตอบโต้กับผู้คนจำนวนมากดังนั้นฉันคิดว่าฉันโพสต์การอัปเดต คำเตือนเกี่ยวกับคำตอบที่ได้รับการยอมรับด้านล่างซึ่งเพิ่มโดย Oskar เกี่ยวกับตัวละครต่างประเทศนั้นถูกต้องสมบูรณ์และฉันใช้งานไม่กี่ครั้งเนื่องจากใช้ContentDisposition
คลาส ฉันได้อัปเดตการใช้งานเพื่อแก้ไขปัญหานี้ตั้งแต่ ในขณะที่รหัสด้านล่างมาจากการอวตารล่าสุดของปัญหานี้ในแอป ASP.NET Core (Full Framework) มันควรทำงานกับการเปลี่ยนแปลงเล็กน้อยในแอปพลิเคชัน MVC รุ่นเก่าเช่นกันเนื่องจากฉันใช้System.Net.Http.Headers.ContentDispositionHeaderValue
คลาส
using System.Net.Http.Headers;
public IActionResult Download()
{
Document document = ... //Obtain document from database context
//"attachment" means always prompt the user to download
//"inline" means let the browser try and handle it
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = document.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
return File(document.Data, document.ContentType);
}
// an entity class for the document in my database
public class Document
{
public string FileName { get; set; }
public string ContentType { get; set; }
public byte[] Data { get; set; }
//Other properties left out for brevity
}