web-dev-qa-db-fra.com

Comment conserver le type de saisie = valeur du champ de fichier après l'échec de la validation dans ASP.NET MVC?

J'ai un formulaire simple dans une application MVC que j'ai créée. Il contient un champ de fichier afin que les utilisateurs puissent télécharger une image. Tout fonctionne très bien.

Le problème, c'est que si la validation du formulaire échoue, le contenu du champ de fichier est perdu (les autres champs restent renseignés, par exemple HtmlHelpers!). Comment garder le champ de fichier rempli après une validation ayant échoué?

TIA!

60
Chaddeus

Les navigateurs sont conçus de cette manière en raison des risques de sécurité. Il est impossible de définir la valeur de la zone de saisie du fichier en source HTML ou en Javascript. Sinon, un script malveillant pourrait voler un fichier privé sans l'attention de l'utilisateur.

Il y a une information intéressante sur le sujet.

57

Autant que je sache, vous ne pouvez pas définir la valeur d'une zone de saisie de fichier HTML. Je suggérerais de coupler la zone de saisie du fichier avec une étiquette ou une zone de texte.

Ensuite, vous pouvez le renseigner avec la valeur de la zone de saisie du fichier à renvoyer ultérieurement.

2
Michael

Je recommanderais de faire la validation au préalable via ajax et d'effectuer une mise à jour partielle de la page. Dans ce cas, vous ne perdrez pas le fichier.

1
AGuyCalledGerald

Si le fichier n'est pas trop gros, vous pouvez le baser en base64 et l'utiliser comme valeur pour un champ caché.

1

Il existe des téléchargeurs de fichiers Flash. Essayez l'un d'entre eux. Certains d'entre eux retombent même dans la zone de saisie de fichier normale si le script flash et Java n'est pas pris en charge. Je conseille de chercher des plugins jQuery. 

1
gokkor

Je ne suis pas d'accord avec le fait que "impossible" soit marqué comme étant la réponse correcte ... Si quelqu'un cherche toujours une possibilité, voici le travail qui m'a aidé J'utilise MVC5. L'idée est d'utiliser une variable de session. J'ai eu l'idée de ASP.Net Form .

Mon Modèle/ViewModel (uniquement les propriétés pertinentes):

public partial class emp_leaves
    {
        public string fileNameOrig { get; set; }
        public byte[] fileContent { get; set; }

        public HttpPostedFileBase uploadFile { get; set; }
    }

Dans mon contrôleur (HttpPost): // Check

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(emp_leaves emp_leaves)
{
    if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
    {
        emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
        emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
        emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);
        Session["emp_leaves.uploadFile"] = emp_leaves.uploadFile; //saving the file in session variable here
    }
    else if (Session["emp_leaves.uploadFile"] != null)
    {//if re-submitting after a failed validation you will reach here.
        emp_leaves.uploadFile = (HttpPostedFileBase)Session["emp_leaves.uploadFile"];
        if (emp_leaves.uploadFile != null && emp_leaves.uploadFile.ContentLength>0 && !string.IsNullOrEmpty(emp_leaves.uploadFile.FileName))
        {
            emp_leaves.fileNameOrig = Path.GetFileName(emp_leaves.uploadFile.FileName);
            emp_leaves.uploadFile.InputStream.Position = 0;
            emp_leaves.fileContent = new byte[emp_leaves.uploadFile.ContentLength];
            emp_leaves.uploadFile.InputStream.Read(emp_leaves.fileContent, 0, emp_leaves.uploadFile.ContentLength);    
        }
    }
//code to save follows here...
}

Enfin dans ma vue d'édition: ici, je montre sous condition le contrôle de téléchargement de fichier.

< script type = "text/javascript" >
  $("#removefile").on("click", function(e) {
    if (!confirm('Delete File?')) {
      e.preventDefault();
      return false;
    }
    $('#fileNameOrig').val('');
    //toggle visibility for concerned div
    $('#downloadlrfdiv').hide();
    $('#uploadlrfdiv').show();
    return false;
  }); <
/script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
@model PPMSWEB.Models.emp_leaves @{ HttpPostedFileBase uploadFileSession = Session["emp_leaves.uploadFile"] == null ? null : (HttpPostedFileBase)Session["emp_leaves.uploadFile"]; } @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data"
})) { @Html.AntiForgeryToken()
<div class="row">
  @*irrelevant content removed*@
  <div id="downloadlrfdiv" @((!String.IsNullOrEmpty(Model.fileNameOrig) && (Model.uploadFile==n ull || uploadFileSession !=null)) ? "" : "style=display:none;")>
    <label>Attachment</label>
    <span>
            <strong>
                <a id="downloadlrf" href="@(uploadFileSession != null? "" : Url.Action("DownloadLRF", "emp_leaves", new { empLeaveId = Model.ID }))" class="text-primary ui-button-text-icon-primary" title="Download attached file">
                    @Model.fileNameOrig
                </a>
            </strong>
            @if (isEditable && !Model.readonlyMode)
            {
                @Html.Raw("&nbsp");
                <a id="removefile" class="btn text-danger lead">
                    <strong title="Delete File" class="glyphicon glyphicon-minus-sign">  </strong>
                </a>
            }
            </span>
  </div>
  <div id="uploadlrfdiv" @(!(!String.IsNullOrEmpty(Model.fileNameOrig) && Model.uploadFile==n ull) && !Model.readonlyMode ? "" : "style=display:none;")>
    <label>Upload File</label> @Html.TextBoxFor(model => model.uploadFile, new { @type = "file", @class = "btn btn-default", @title = "Upload file (max 300 KB)" }) @Html.ValidationMessageFor(x => x.uploadFile)
  </div>
</div>
}

0
Arfath

Vous ne pouvez pas définir la valeur d'une zone de saisie de fichier HTML. Pour résoudre ce problème, remplacez la zone de téléchargement de fichier par un champ de saisie masqué lors de la génération du formulaire après validation.

Lors de la soumission, vous renseignez le champ masqué avec la valeur de la zone de saisie du fichier (à resoumettre ultérieurement). N'oubliez pas que le nom du fichier caché ou du champ masqué est présent à tout moment (pas les deux):

Remarque: Le code ci-dessous est destiné uniquement à illustration/explication. Remplacez-le par le code correspondant à la langue que vous utilisez.

<?php /* You may need to sanitize the value of $_POST['file_upload']; 
* this is just a start */
if(isset($_POST['file_upload']) && !empty($_POST['file_upload'])){ ?>
<input type="hidden" name="file_upload" value="<?php print($_POST['file_upload']); ?>" />
<?php } else { ?>
<input type="file" name="file_upload" />
<?php } ?>
0
Agi Hammerthief