ความแตกต่างระหว่างผลลัพธ์ไฟล์สี่ไฟล์ใน ASP.NET MVC คืออะไร


136

ASP.NET มีผลลัพธ์ไฟล์สี่ประเภท:

  • FileContentResult: ส่งเนื้อหาของไฟล์ไบนารีไปยังการตอบกลับ
  • FilePathResult: ส่งเนื้อหาของไฟล์ไปยังการตอบกลับ
  • FileResult: ส่งคืนเอาต์พุตไบนารีเพื่อเขียนไปยังการตอบกลับ
  • FileStreamResult: ส่งเนื้อหาไบนารีไปยังการตอบสนองโดยใช้อินสแตนซ์กระแสข้อมูล

คำอธิบายเหล่านั้นมาจาก MSDN และมีข้อยกเว้นของ FileStreamResult สามเสียงแรกที่เหมือนกัน ดังนั้นความแตกต่างระหว่างพวกเขาคืออะไร?

คำตอบ:


176

FileResult เป็นคลาสพื้นฐานที่เป็นนามธรรมสำหรับผู้อื่นทั้งหมด

  • FileContentResult - คุณใช้มันเมื่อคุณมีอาร์เรย์ไบต์ที่คุณต้องการจะส่งคืนเป็นไฟล์
  • FilePathResult - เมื่อคุณมีไฟล์บนดิสก์และต้องการคืนเนื้อหา (ให้เส้นทาง)
  • FileStreamResult - คุณเปิดกระแสข้อมูลคุณต้องการคืนเนื้อหาเป็นไฟล์

อย่างไรก็ตามคุณแทบจะไม่ต้องใช้คลาสเหล่านี้ - คุณสามารถใช้Controller.Fileโอเวอร์โหลดตัวใดตัวหนึ่งแล้วปล่อยให้ ASP.NET MVC เป็นเวทย์มนตร์ให้คุณ


29

เป็นคำถามที่ดี ... และสมควรได้รับรายละเอียดเพิ่มเติม ฉันพบว่าตัวเองอยู่ที่นี่อันเป็นผลมาจากสถานการณ์ที่น่าสนใจ เราได้ส่งไฟล์แนบ PDF บางส่วนผ่านสภาพแวดล้อม MVC3 / C # รหัสของเราได้รับการปล่อยตัวออกมาและเราเริ่มได้รับคำตอบจากลูกค้าของเราว่าการดาวน์โหลดนั้นมีพฤติกรรมแปลก ๆ เมื่อพวกเขาใช้ Chrome และประเภทของไฟล์นั้นถูกแปลงเป็น 'pdf-, Attach.pdf-, สิ่งที่แนบมา' ใช่ ... คุณเข้าใจแล้ว ... สิ่งทั้งหมด ดังนั้นหนึ่งสามารถเขียนมันเป็นเพียงแค่ 'pdf' และไฟล์จะยังคงบันทึกเหมือนเดิม แต่สิ่งที่เป็นระเบียบ!

ดังนั้นเพื่ออธิบายสถานการณ์เริ่มต้นเราได้ตั้งค่าส่วนหัว 'เนื้อหา - การจัดการ' แล้วส่งคืน FileContentResult ...

var cd = new System.Net.Mime.ContentDisposition
            {
                FileName = result.Attachment.FileName,
                Inline = false
            };
            Response.AppendHeader("Content-Disposition", cd.ToString());

return File(result.Attachment.Data, MimeExtensionHelper.GetMimeType(result.Attachment.FileName), result.Attachment.FileName);

ดูเหมือนดี ทำงานได้ดีใน IE ดังนั้นฉันจึงทำการวิจัยและลองใช้ FileStreamResult แทน (ทำให้ setter Content-Disposition):

MemoryStream dataStream = new MemoryStream();
dataStream.Write(result.Attachment.Data, 0, result.Attachment.Data.Length);
dataStream.Position = 0;
return new FileStreamResult(dataStream, MimeExtensionHelper.GetMimeType(result.Attachment.FileName));

มันแก้ไขปัญหาใน Chrome! อืม ... แต่ทำไมในการห่ามฉันควรจะต้องใช้อาร์เรย์ไบต์ที่ดีของฉันอย่างสมบูรณ์แบบและสตรีมมันแล้วส่งคืนผ่านทางนี้เพื่อให้ชื่อไฟล์ใช้งานได้ใช่ไหม

จากนั้นพู้ทำเล่นมา

ด้วย FileContentResult ฉันได้ 2 การกำจัดเนื้อหาในส่วนหัว ด้วย FileStreamResult ฉันได้ 1

FileContentResult ผนวกส่วนหัวของ Content-Disposition เมื่อระบุชื่อไฟล์และ Chrome พิจารณาว่าส่วนหัวหลายส่วนเป็นข้อผิดพลาด

ปฏิกิริยาแปลก ๆ ... แต่ก็เป็นสิ่งที่ดีที่จะรู้


3
เพียงปลายใน. NET 4+ คุณสามารถใช้System.Web.MimeMapping.GetMimeMapping(filename)เพื่อรวบรวมประเภท mime หากคุณไม่สามารถเข้าถึงได้อย่างง่ายดาย
GONeale

4
การระบุชื่อไฟล์ให้กับFileผลลัพธ์หมายถึงการตั้งค่าFileDownloadNameคุณสมบัติซึ่งตั้งค่าContent-Dispositionส่วนหัวให้คุณ และรองรับชื่อไฟล์ utf-8 อย่างถูกต้องซึ่งไม่ได้เป็นตัวContentDispositionช่วยคลาส (ดูความคิดเห็นของฉันที่นี่เพื่อดูรายละเอียดเพิ่มเติม)
Frédéric

1
ใช่ขอบคุณ @ Frédéricคุณคนเดียวจากโพสต์ SO ทั้งหมดได้อธิบายให้ฉันฟังว่าเกิดอะไรขึ้น!
Nacht
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.