web-dev-qa-db-fra.com

Télécharger un fichier de tout type dans Asp.Net MVC en utilisant FileResult?

On m'a suggéré d'utiliser FileResult pour permettre aux utilisateurs de télécharger des fichiers à partir de mon application Asp.Net MVC. Mais le seul exemple que je puisse trouver concerne toujours les fichiers image (spécifiant le type de contenu image/jpeg).

Mais si je ne peux pas connaître le type de fichier? Je souhaite que les utilisateurs puissent télécharger à peu près tous les fichiers de l’archive de mon site.

J'avais lu une méthode pour le faire (voir un article précédent pour le code), cela fonctionne bien, sauf pour une chose: le nom du fichier qui apparaît dans la boîte de dialogue Enregistrer sous est concaténé à partir du chemin du fichier avec underscores (folder_folder_file.ext). De plus, il semble que les gens pensent que je devrais renvoyer un FileResult au lieu d'utiliser cette classe personnalisée pour laquelle j'ai trouvé BinaryContentResult.

Quelqu'un sait-il comment "faire" un tel téléchargement dans MVC?

EDIT: J'ai eu la réponse (ci-dessous), mais je pensais que je devrais publier le code de travail complet si quelqu'un d'autre est intéressé:

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;
}
215
Anders

Vous pouvez simplement spécifier le type MIME générique du flux d'octets:

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);
}
392
Ian Henry

Le framework MVC supporte cela nativement. Le contrôleur System.Web.MVC.Controller.File fournit des méthodes pour renvoyer un fichier par nom / flux / array =.

Par exemple, en utilisant un chemin virtuel vers le fichier, vous pouvez procéder comme suit.

return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet,  Path.GetFileName(virtualFilePath));
102
Jonathan

Si vous utilisez .NET Framework 4.5, utilisez le MimeMapping.GetMimeMapping (string FileName) pour obtenir le type MIME de votre fichier. Voici comment je l'ai utilisé dans mon action.

return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);
32
Salman Hasrat Khan

Phil Haack a un Nice article où il a créé une classe de résultats Action de téléchargement de fichier Custome. Il vous suffit de spécifier le chemin virtuel du fichier et le nom à enregistrer.

Je l'ai utilisé une fois et voici mon code.

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

Dans mon exemple, je stockais le chemin physique des fichiers, de sorte que j'ai utilisé cette méthode d'assistance - que j'ai trouvé quelque part dont je ne me souviens plus - pour le convertir en chemin virtuel.

        private string GetVirtualPath(string physicalPath)
        {
            string rootpath = Server.MapPath("~/");

            physicalPath = physicalPath.Replace(rootpath, "");
            physicalPath = physicalPath.Replace("\\", "/");

            return "~/" + physicalPath;
        }

Voici la classe complète tirée de l'article de Phill Haack

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);
    }
}
10
Manaf Abu.Rous

Merci à Ian Henry!

Au cas où vous auriez besoin de pour obtenir un fichier à partir de MS SQL Server , voici la solution.

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 est le modèle EntityFramework et MyFiles présente le tableau dans votre base de données. FileData est varbinary(MAX) dans MyFiles table.

5
Developer

son simple suffit de donner votre chemin physique dans directoryPath avec le nom de fichier

public FilePathResult GetFileFromDisk(string fileName)
{
    return File(directoryPath, "multipart/form-data", fileName);
}
2
DARSHAN SHINDE
   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);
        }
0
hossein zakizadeh