854 votes

Téléchargement de fichier ASP.NET MVC 3.0

Je veux télécharger le fichier en . Comment puis-je télécharger le fichier à l'aide de html input file de contrôle?

1166voto

Darin Dimitrov Points 528142

Vous n'avez pas utiliser un fichier de contrôle d'entrée. Côté serveur contrôles ne sont pas utilisés dans ASP.NET MVC. Extraire le blog suivant qui illustre la façon d'atteindre cet objectif dans ASP.NET MVC.

Ainsi, vous commencerez par créer un formulaire HTML qui contient un fichier d'entrée:

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="file" />
    <input type="submit" value="OK" />
}

et puis vous avez un contrôleur pour gérer l'upload:

public class HomeController : Controller
{
    // This action renders the form
    public ActionResult Index()
    {
        return View();
    }

    // This action handles the form POST and the upload
    [HttpPost]
    public ActionResult Index(HttpPostedFileBase file)
    {
        // Verify that the user selected a file
        if (file != null && file.ContentLength > 0) 
        {
            // extract only the fielname
            var fileName = Path.GetFileName(file.FileName);
            // store the file inside ~/App_Data/uploads folder
            var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
            file.SaveAs(path);
        }
        // redirect back to the index action to show the form once again
        return RedirectToAction("Index");        
    }
}

163voto

Arthur Points 1064

le transfert de byte[] (par exemple, pour l'enregistrement dans la base de données):

using (MemoryStream ms = new MemoryStream()) {
    file.InputStream.CopyTo(ms);
    byte[] array = ms.GetBuffer();
}

60voto

Lane Points 991

Méthode Alternative pour le transfert de byte[] (pour la sauvegarde de la DB).

@Arthur méthode fonctionne assez bien, mais ne copie pas parfaitement les documents MS Office peut ne pas ouvrir après la récupération de la base de données. MemoryStream.GetBuffer() peut retourner des vide octets à la fin de l'byte[], mais vous pouvez corriger cela en utilisant MemoryStream.ToArray() à la place. Cependant, j'ai trouvé cette solution fonctionne parfaitement pour tous les types de fichiers:

using (var binaryReader = new BinaryReader(file.InputStream))
{
    byte[] array = binaryReader.ReadBytes(file.ContentLength);
}

Voici mon code complet:

La Classe De Document:

public class Document
{
    public int? DocumentID { get; set; }
    public string FileName { get; set; }
    public byte[] Data { get; set; }
    public string ContentType { get; set; }
    public int? ContentLength { get; set; }

    public Document()
    {
        DocumentID = 0;
        FileName = "New File";
        Data = new byte[] { };
        ContentType = "";
        ContentLength = 0;
    }
}

Télécharger Le Fichier:

[HttpGet]
public ActionResult GetDocument(int? documentID)
{
    // Get document from database
    var doc = dataLayer.GetDocument(documentID);

    // Convert to ContentDisposition
    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = doc.FileName, 

        // Prompt the user for downloading; set to true if you want 
        // the browser to try to show the file 'inline' (display in-browser
        // without prompting to download file).  Set to false if you 
        // want to always prompt them to download the file.
        Inline = true, 
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());

    // View document
    return File(doc.Data, doc.ContentType);
}

Téléchargement De Fichiers:

[HttpPost]
public ActionResult GetDocument(HttpPostedFileBase file)
{
    // Verify that the user selected a file
    if (file != null && file.ContentLength > 0)
    {
        // Get file info
        var fileName = Path.GetFileName(file.FileName);
        var contentLength = file.ContentLength;
        var contentType = file.ContentType;

        // Get file data
        byte[] data = new byte[] { };
        using (var binaryReader = new BinaryReader(file.InputStream))
        {
            data = binaryReader.ReadBytes(file.ContentLength);
        }

        // Save to database
        Document doc = new Document()
        {
            FileName = fileName,
            Data = data,
            ContentType = contentType,
            ContentLength = contentLength,
        };
        dataLayer.SaveDocument(doc);

        // Show success ...
        return RedirectToAction("Index");
    }
    else
    {
        // Show error ...
        return View("Foo");
    }
}

Affichage (extrait):

@using (Html.BeginForm("GetDocument", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="file" />
    <input type="submit" value="Upload File" />
}

47voto

Roman Pushkin Points 1492

Souvent, vous voulez passer un viewmodel aussi, et pas seulement un seul fichier. Dans le code ci-dessous, vous trouverez quelques autres fonctionnalités utiles:

  • vérifier si le fichier a été attaché
  • vérifier si la taille du fichier est de 0
  • vérifier si la taille du fichier est supérieure à 4 MO
  • vérifier si la taille du fichier est inférieure à 100 octets
  • la vérification des extensions de fichier

Il pourrait être fait via le code suivant:

[HttpPost]
public ActionResult Index(MyViewModel viewModel)
{
    // if file's content length is zero or no files submitted

    if (Request.Files.Count != 1 || Request.Files[0].ContentLength == 0)
    {
        ModelState.AddModelError("uploadError", "File's length is zero, or no files found");
        return View(viewModel);
    }

    // check the file size (max 4 Mb)

    if (Request.Files[0].ContentLength > 1024 * 1024 * 4)
    {
        ModelState.AddModelError("uploadError", "File size can't exceed 4 MB");
        return View(viewModel);
    }

    // check the file size (min 100 bytes)

    if (Request.Files[0].ContentLength < 100)
    {
        ModelState.AddModelError("uploadError", "File size is too small");
        return View(viewModel);
    }

    // check file extension

    string extension = Path.GetExtension(Request.Files[0].FileName).ToLower();

    if (extension != ".pdf" && extension != ".doc" && extension != ".docx" && extension != ".rtf" && extension != ".txt")
    {
        ModelState.AddModelError("uploadError", "Supported file extensions: pdf, doc, docx, rtf, txt");
        return View(viewModel);
    }

    // extract only the filename
    var fileName = Path.GetFileName(Request.Files[0].FileName);

    // store the file inside ~/App_Data/uploads folder
    var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);

    try
    {
        if (System.IO.File.Exists(path))
            System.IO.File.Delete(path);

        Request.Files[0].SaveAs(path);
    }
    catch (Exception)
    {
        ModelState.AddModelError("uploadError", "Can't save file to disk");
    }

    if(ModelState.IsValid)
    {
        // put your logic here

        return View("Success");
    }

    return View(viewModel);         
}

Assurez-vous que vous avez

@Html.ValidationMessage("uploadError")

de votre point de vue pour les erreurs de validation.

Aussi garder à l'esprit que le défaut de demande maximale, la longueur est de 4 mo (maxRequestLength = 4096), pour télécharger des fichiers plus volumineux, vous devez modifier ce paramètre dans le web.config:

<system.web>
    <httpRuntime maxRequestLength="40960" executionTimeout="1100" />

(40960 = 40 MO ici).

Délai d'exécution est le nombre entier de secondes. Vous pouvez le changer pour permettre à d'énormes fichiers de téléchargements.

32voto

msoliman Points 732

dans la vue:

<form action="Categories/Upload" enctype="multipart/form-data" method="post">
    <input type="file" name="Image">
    <input type="submit" value"Save">
</form>

alors que le code suivant dans le contrôleur:

  public ActionResult Upload()
    {
        foreach (string file in Request.Files)
        {
            var hpf = this.Request.Files[file];
            if (hpf.ContentLength == 0)
            {
                continue;
            }

            string savedFileName = Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory, "PutYourUploadDirectoryHere");
                savedFileName = Path.Combine(savedFileName, Path.GetFileName(hpf.FileName));

            hpf.SaveAs(savedFileName);
        }

    ...
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X