Aide HTML pour <input type = "file" />

124

Y a-t-il un HTMLHelperpour le téléchargement de fichiers? Plus précisément, je recherche un remplacement de

<input type="file"/>

en utilisant ASP.NET MVC HTMLHelper.

Ou, si j'utilise

using (Html.BeginForm()) 

Quel est le contrôle HTML pour le téléchargement de fichiers?

Graviton
la source

Réponses:

207

Fichier de téléchargement HTML ASP MVC 3.

Modèle : ( Notez que FileExtensionsAttribute est disponible dans MvcFutures. Il validera les extensions de fichier côté client et côté serveur. )

public class ViewModel
{
    [Required, Microsoft.Web.Mvc.FileExtensions(Extensions = "csv", 
             ErrorMessage = "Specify a CSV file. (Comma-separated values)")]
    public HttpPostedFileBase File { get; set; }
}

Affichage HTML :

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })
    @Html.ValidationMessageFor(m => m.File)
}

Action du contrôleur :

[HttpPost]
public ActionResult Action(ViewModel model)
{
    if (ModelState.IsValid)
    {
        // Use your file here
        using (MemoryStream memoryStream = new MemoryStream())
        {
            model.File.InputStream.CopyTo(memoryStream);
        }
    }
}
Paulius Zaliaduonis
la source
Cela ne rend pas une entrée de fichier <input type="file" />, seulement une zone de texte
Ben
@PauliusZaliaduonis avec la ligne Microsoft.Web.Mvc.FileExtensions le MVC est souligné en rouge. Comment résoudre ce problème?
Pomster le
1
@pommy Notez que FileExtensionsAttribute est disponible dans MvcFutures (à partir de MVC3). Vous pouvez utiliser les sources d'ici: Sources ou il est disponible dans .NET Framework 4.5, voir la documentation MSDN
Paulius Zaliaduonis
1
Malheureusement, l'attribut FileExtension ne semble pas fonctionner avec le type de propriétés HttpPostedFileBase, mais il semble plutôt une chaîne uniquement. Au moins, il n'a jamais accepté pdf comme extension valide.
Serj Sagan
Cela ajoutera un attribut de valeur (valeur = "") qui ne sera pas validé comme HTML5 valide. La valeur n'est pas valide sur le fichier et l'image des types d'entrée. Je ne vois aucun moyen de supprimer l'attribut value. Il semble être codé en dur.
Dan Friedman
19

Vous pouvez aussi utiliser:

@using (Html.BeginForm("Upload", "File", FormMethod.Post, new { enctype = "multipart/form-data" }))
{ 
    <p>
        <input type="file" id="fileUpload" name="fileUpload" size="23" />
    </p>
    <p>
        <input type="submit" value="Upload file" /></p> 
}
balexandre
la source
6

Ou vous pouvez le faire correctement:

Dans votre classe d'extension HtmlHelper:

public static MvcHtmlString FileFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        return helper.FileFor(expression, null);
    }

public static MvcHtmlString FileFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    {
        var builder = new TagBuilder("input");

        var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));
        builder.GenerateId(id);
        builder.MergeAttribute("name", id);
        builder.MergeAttribute("type", "file");

        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        // Render tag
        return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
    }

Cette ligne:

var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression));

Génère un identifiant unique au modèle, que vous connaissez dans les listes et tout. modèle [0] .Name etc.

Créez la propriété correcte dans le modèle:

public HttpPostedFileBase NewFile { get; set; }

Ensuite, vous devez vous assurer que votre formulaire enverra des fichiers:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { enctype = "multipart/form-data" }))

Alors voici votre aide:

@Html.FileFor(x => x.NewFile)
Tod
la source
Cette solution est plus agréable pour les yeux et me permet de rester cohérent avec les méthodes d'aide @Html.
Yahfoufi
4

Version améliorée de la réponse de Paulius Zaliaduonis:

Pour que la validation fonctionne correctement, j'ai dû changer le modèle en:

public class ViewModel
{
      public HttpPostedFileBase File { get; set; }

        [Required(ErrorMessage="A header image is required"), FileExtensions(ErrorMessage = "Please upload an image file.")]
        public string FileName
        {
            get
            {
                if (File != null)
                    return File.FileName;
                else
                    return String.Empty;
            }
        }
}

et la vue sur:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })
    @Html.ValidationMessageFor(m => m.FileName)
}

Ceci est nécessaire car ce que @Serj Sagan a écrit à propos de l'attribut FileExtension fonctionnant uniquement avec des chaînes.

BornToCode
la source
Ne pouvez-vous pas fusionner cette réponse dans la réponse de Paulius?
Graviton
2

Pour l'utiliser BeginForm, voici comment l'utiliser:

 using(Html.BeginForm("uploadfiles", 
"home", FormMethod.POST, new Dictionary<string, object>(){{"type", "file"}})
Graviton
la source
2
Vous dites d'abord comment générer un élément d'entrée, et maintenant vous parlez de la façon de générer un élément de formulaire? Est-ce vraiment votre réponse?
pupeno
0

Cela fonctionne également:

Modèle:

public class ViewModel
{         
    public HttpPostedFileBase File{ get; set; }
}

Vue:

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new 
                                       { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.File, new { type = "file" })       
}

Action du contrôleur:

[HttpPost]
public ActionResult Action(ViewModel model)
{
    if (ModelState.IsValid)
    {
        var postedFile = Request.Files["File"];

       // now you can get and validate the file type:
        var isFileSupported= IsFileSupported(postedFile);

    }
}

public bool IsFileSupported(HttpPostedFileBase file)
            {
                var isSupported = false;

                switch (file.ContentType)
                {

                    case ("image/gif"):
                        isSupported = true;
                        break;

                    case ("image/jpeg"):
                        isSupported = true;
                        break;

                    case ("image/png"):
                        isSupported = true;
                        break;


                    case ("audio/mp3"):  
                        isSupported = true;
                        break;

                    case ("audio/wav"):  
                        isSupported = true;
                        break;                                 
                }

                return isSupported;
            }

Liste des types de contenu

Eyal
la source
-2

C'est un peu hacky je suppose, mais cela entraîne l'application des attributs de validation corrects, etc.

@Html.Raw(Html.TextBoxFor(m => m.File).ToHtmlString().Replace("type=\"text\"", "type=\"file\""))
Luke Schafer
la source