Загрузить файл любого типа в Asp.Net MVC с помощью FileResult?
Я предложил мне, чтобы я использовал FileResult, чтобы пользователи могли загружать файлы из моего приложения ASP.NET MVC. Но единственные примеры, которые я могу найти, всегда связаны с файлами изображений (с указанием типа содержимого image/jpeg).
Но что, если я не могу узнать тип файла? Я хочу, чтобы пользователи могли загружать практически любой файл из файловой области моего сайта.
Я прочитал один из способов сделать это (см. предыдущий пост для кода), который на самом деле отлично работает, за исключением одного: имя файла который появляется в диалоговом окне "Сохранить как", конкатенируется из пути файла с помощью подчеркивания (folder_folder_file.ext). Кроме того, кажется, люди думают, что я должен вернуть FileResult вместо использования этого настраиваемого класса, который я нашел BinaryContentResult.
Кто-нибудь знает "правильный" способ сделать такую загрузку в MVC?
EDIT:
Я получил ответ (ниже), но просто подумал, что должен опубликовать полный рабочий код, если кому-то интересен:
public ActionResult Download(string filePath, string fileName)
{
string fullName = Path.Combine(GetBaseDir(), filePath, fileName);
byte[] fileBytes = GetFile(fullName);
return File(
fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
byte[] GetFile(string s)
{
System.IO.FileStream fs = System.IO.File.OpenRead(s);
byte[] data = new byte[fs.Length];
int br = fs.Read(data, 0, data.Length);
if (br != fs.Length)
throw new System.IO.IOException(s);
return data;
}
Ответы
Ответ 1
Вы можете просто указать общий тип MIME-потока октетов:
public FileResult Download()
{
byte[] fileBytes = System.IO.File.ReadAllBytes(@"c:\folder\myfile.ext");
string fileName = "myfile.ext";
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
Ответ 2
Среда MVC поддерживает это изначально. Контроллер System.Web.MVC.Controller.File предоставляет методы для возврата файла name/поток/массив.
Например, используя виртуальный путь к файлу, вы можете сделать следующее.
return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(virtualFilePath));
Ответ 3
Если вы используете .NET Framework 4.5, вы используете MimeMapping.GetMimeMapping (string FileName), чтобы получить MIME-тип для ваш файл. Вот как я использовал его в своих действиях.
return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);
Ответ 4
У Phil Haack есть хорошая статья где он создал класс результата действия файла Custome. Вам нужно указать виртуальный путь файла и имя, которое будет сохранено как.
Я использовал его один раз и здесь свой код.
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Download(int fileID)
{
Data.LinqToSql.File file = _fileService.GetByID(fileID);
return new DownloadResult { VirtualPath = GetVirtualPath(file.Path),
FileDownloadName = file.Name };
}
В моем примере я хранили физический путь к файлам, поэтому я использовал этот вспомогательный метод, который я нашел где-то, что не могу вспомнить, - чтобы преобразовать его в виртуальный путь
private string GetVirtualPath(string physicalPath)
{
string rootpath = Server.MapPath("~/");
physicalPath = physicalPath.Replace(rootpath, "");
physicalPath = physicalPath.Replace("\\", "/");
return "~/" + physicalPath;
}
Здесь полный класс, взятый из статьи Филла Хаака
public class DownloadResult : ActionResult {
public DownloadResult() {}
public DownloadResult(string virtualPath) {
this.VirtualPath = virtualPath;
}
public string VirtualPath {
get;
set;
}
public string FileDownloadName {
get;
set;
}
public override void ExecuteResult(ControllerContext context) {
if (!String.IsNullOrEmpty(FileDownloadName)) {
context.HttpContext.Response.AddHeader("content-disposition",
"attachment; filename=" + this.FileDownloadName)
}
string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
context.HttpContext.Response.TransmitFile(filePath);
}
}
Ответ 5
Благодаря Ян Генри!
Если вам нужно получить файл с MS SQL Server, это решение.
public FileResult DownloadDocument(string id)
{
if (!string.IsNullOrEmpty(id))
{
try
{
var fileId = Guid.Parse(id);
var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId);
if (myFile != null)
{
byte[] fileBytes = myFile.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName);
}
}
catch
{
}
}
return null;
}
Где AppModel - модель EntityFramework
, а MyFiles - таблица в вашей базе данных.
FileDatastrong > - varbinary(MAX)
в таблице MyFiles.
Ответ 6
его просто указать свой физический путь в directoryPath с именем файла
public FilePathResult GetFileFromDisk(string fileName)
{
return File(directoryPath, "multipart/form-data", fileName);
}
Ответ 7
public ActionResult Download()
{
var document = //Obtain document from database context
var cd = new System.Net.Mime.ContentDisposition
{
FileName = document.FileName,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
}
Ответ 8
if (string.IsNullOrWhiteSpace(fileName)) вернуть содержимое ("имя файла отсутствует");
var path = Path.Combine(your path, your filename);
var stream = new FileStream(path, FileMode.Open);
return File(stream, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
Ответ 9
GetFile должен закрывать файл (или открывать его при использовании). Затем вы можете удалить файл после преобразования в байты - загрузка будет выполнена в этом байтовом буфере.
byte[] GetFile(string s)
{
byte[] data;
using (System.IO.FileStream fs = System.IO.File.OpenRead(s))
{
data = new byte[fs.Length];
int br = fs.Read(data, 0, data.Length);
if (br != fs.Length)
throw new System.IO.IOException(s);
}
return data;
}
Итак, в вашем методе загрузки...
byte[] fileBytes = GetFile(file);
// delete the file after conversion to bytes
System.IO.File.Delete(file);
// have the file download dialog only display the base name of the file return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(file));