Скачать файл любого типа в Asp.Net MVC, используя FileResult? - PullRequest
212 голосов
/ 31 августа 2010

Мне предложили использовать 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;
}

Ответы [ 8 ]

389 голосов
/ 31 августа 2010

Вы можете просто указать общий 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);
}
101 голосов
/ 05 января 2013

Платформа MVC поддерживает это изначально.Контроллер System.Web.MVC.Controller.File предоставляет методы для возврата файла по name / stream / array .

Например, используя виртуальный путь к файлу, вы можете сделать следующее:

return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet,  Path.GetFileName(virtualFilePath));
32 голосов
/ 14 апреля 2013

Если вы используете .NET Framework 4.5, вы используете MimeMapping.GetMimeMapping (строка FileName), чтобы получить MIME-тип для вашего файла.Вот как я использовал это в своих действиях.

return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);
10 голосов
/ 31 августа 2010

У Фила Хаака есть замечательная статья , в которой он создал класс Результат действия при загрузке файла 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 голосов
/ 21 марта 2014

Благодаря Иену Генри !

В случае, если вам нужно для получения файла с 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 представляет таблицу в вашей базе данных. FileData равно varbinary(MAX) в MyFiles таблица.

2 голосов
/ 24 июня 2015

просто укажите свой физический путь в directoryPath с именем файла

public FilePathResult GetFileFromDisk(string fileName)
{
    return File(directoryPath, "multipart/form-data", fileName);
}
0 голосов
/ 04 июля 2019

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);
0 голосов
/ 17 декабря 2013

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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...