Carga de archivos MVC 3 y enlace de modelos

91

Tengo una carga de formulario que funciona, pero me gustaría pasar la información del modelo para mi base de datos para guardar el archivo con un nombre diferente, por supuesto.

Aquí está mi vista de Razor:

@model CertispecWeb.Models.Container

@{
  ViewBag.Title = "AddDocuments";
}

<h2>AddDocuments</h2>

@Model.ContainerNo

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

Aquí está mi controlador:

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
     if (file.ContentLength > 0)
     {
        var fileName = Path.GetFileName(file.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"),
                       containers.ContainerNo);
        file.SaveAs(path);
     }

     return RedirectToAction("Index");
}

La información del modelo no se transmite al controlador. He leído que es posible que necesite actualizar el modelo, ¿cómo lo haría?

Francis
fuente
2
Consulte stackoverflow.com/questions/9411563/… para un problema relacionado
LCJ

Respuestas:

123

Su formulario no contiene ninguna etiqueta de entrada que no sea el archivo, por lo que en la acción de su controlador no puede esperar obtener nada más que el archivo cargado (eso es todo lo que se envía al servidor). Una forma de lograr esto sería incluir una etiqueta oculta que contenga la identificación del modelo que le permitirá recuperarlo de su almacén de datos dentro de la acción del controlador en la que está publicando (use esto si se supone que el usuario no debe modificar el modelo pero simplemente adjunte un archivo):

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.HiddenFor(x => x.Id)
    <input type="file" name="file" id="file" />
    <input type="submit" value="submit" />
}

y luego en la acción de su controlador:

[HttpPost]
public ActionResult Uploadfile(int id, HttpPostedFileBase file)
{
    Containers containers = Repository.GetContainers(id);
    ...
}

Por otro lado, si desea permitir que el usuario modifique este modelo, deberá incluir los campos de entrada adecuados para cada campo de su modelo que desee que se envíe al servidor:

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(x => x.Prop1)
    @Html.TextBoxFor(x => x.Prop2)
    @Html.TextBoxFor(x => x.Prop3)
    <input type="file" name="file" id="file" />
    <input type="submit" value="submit" />
}

y luego tendrá el encuadernador de modelos predeterminado reconstruir este modelo a partir de la solicitud:

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
    ...
}
Darin Dimitrov
fuente
1
También obtengo filecomo nully Request.Files.Countes 0, ¿habría alguna diferencia si el formes un AjaxFormy también hay routeValues?
bjan
8

Resuelto

Modelo

public class Book
{
public string Title {get;set;}
public string Author {get;set;}
}

Controlador

public class BookController : Controller
{
     [HttpPost]
     public ActionResult Create(Book model, IEnumerable<HttpPostedFileBase> fileUpload)
     {
         throw new NotImplementedException();
     }
}

Y ver

@using (Html.BeginForm("Create", "Book", FormMethod.Post, new { enctype = "multipart/form-data" }))
{      
     @Html.EditorFor(m => m)

     <input type="file" name="fileUpload[0]" /><br />      
     <input type="file" name="fileUpload[1]" /><br />      
     <input type="file" name="fileUpload[2]" /><br />      

     <input type="submit" name="Submit" id="SubmitMultiply" value="Upload" />
}

Tenga en cuenta que el título del parámetro de la acción del controlador debe coincidir con el nombre de los elementos de entrada IEnumerable<HttpPostedFileBase> fileUpload->name="fileUpload[0]"

fileUpload debe coincidir con

isxaker
fuente
2
Esta solución es la única que encontré para varios archivos. Gracias por compartir tu código.
Rojan Gh.
6

Si no siempre publicará imágenes en su acción, puede hacer algo como esto:

[HttpPost]
public ActionResult Uploadfile(Container container, HttpPostedFileBase file) 
{
    //do container stuff

    if (Request.Files != null)
    {
        foreach (string requestFile in Request.Files)
        {
            HttpPostedFileBase file = Request.Files[requestFile]; 
            if (file.ContentLength > 0)
            {
                string fileName = Path.GetFileName(file.FileName);
                string directory = Server.MapPath("~/App_Data/uploads/");
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
                string path = Path.Combine(directory, fileName);
                file.SaveAs(path);
            }
        }
    }

} 
jhatcher9999
fuente
1

Para varios archivos; tenga en cuenta el atributo " múltiple " más nuevo para la entrada:

Formar:

@using (Html.BeginForm("FileImport","Import",FormMethod.Post, new {enctype = "multipart/form-data"}))
{
    <label for="files">Filename:</label>
    <input type="file" name="files" multiple="true" id="files" />
    <input type="submit"  />
}

Controlador:

[HttpPost]
public ActionResult FileImport(IEnumerable<HttpPostedFileBase> files)
{
    return View();
}
Mcfea
fuente
1

Primera descarga del archivo jquery.form.js desde la siguiente URL

http://plugins.jquery.com/form/

Escriba el código a continuación en cshtml

@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmTemplateUpload" }))
{
    <div id="uploadTemplate">

        <input type="text" value="Asif" id="txtname" name="txtName" />


        <div id="dvAddTemplate">
            Add Template
            <br />
            <input type="file" name="file" id="file" tabindex="2" />
            <br />
            <input type="submit" value="Submit" />
            <input type="button" id="btnAttachFileCancel" tabindex="3" value="Cancel" />
        </div>

        <div id="TemplateTree" style="overflow-x: auto;"></div>
    </div>

    <div id="progressBarDiv" style="display: none;">
        <img id="loading-image" src="~/Images/progress-loader.gif" />
    </div>

}


<script type="text/javascript">

    $(document).ready(function () {
        debugger;
        alert('sample');
        var status = $('#status');
        $('#frmTemplateUpload').ajaxForm({
            beforeSend: function () {
                if ($("#file").val() != "") {
                    //$("#uploadTemplate").hide();
                    $("#btnAction").hide();
                    $("#progressBarDiv").show();
                    //progress_run_id = setInterval(progress, 300);
                }
                status.empty();
            },
            success: function () {
                showTemplateManager();
            },
            complete: function (xhr) {
                if ($("#file").val() != "") {
                    var millisecondsToWait = 500;
                    setTimeout(function () {
                        //clearInterval(progress_run_id);
                        $("#uploadTemplate").show();
                        $("#btnAction").show();
                        $("#progressBarDiv").hide();
                    }, millisecondsToWait);
                }
                status.html(xhr.responseText);
            }
        });

    });


</script>

Método de acción: -

 public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }

 public void Upload(HttpPostedFileBase file, string txtname )
        {

            try
            {
                string attachmentFilePath = file.FileName;
                string fileName = attachmentFilePath.Substring(attachmentFilePath.LastIndexOf("\\") + 1);

           }
            catch (Exception ex)
            {

            }
        }
As
fuente