Przesyłanie plików MVC 3 i powiązanie modelu

91

Mam załadowany formularz, który działa, ale chciałbym przekazać informacje o modelu do mojej bazy danych, aby zapisać plik pod inną nazwą.

Oto mój widok 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" />
}

Oto mój kontroler:

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

Informacje o modelu nie są przekazywane do kontrolera. Przeczytałem, że może być konieczna aktualizacja modelu, jak mam to zrobić?

Francis
źródło
2
Skorzystaj ze strony stackoverflow.com/questions/9411563/…, aby znaleźć powiązany problem
LCJ,

Odpowiedzi:

123

Twój formularz nie zawiera żadnego znacznika wejściowego poza plikiem, więc w akcji kontrolera nie możesz oczekiwać, że otrzymasz coś innego niż przesłany plik (to wszystko, co jest wysyłane na serwer). Jednym ze sposobów na osiągnięcie tego byłoby dołączenie ukrytego tagu zawierającego identyfikator modelu, który pozwoli ci pobrać go z magazynu danych wewnątrz akcji kontrolera, do której wysyłasz (użyj tego, jeśli użytkownik nie ma modyfikować modelu, ale po prostu załącz plik):

@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" />
}

a następnie w akcji kontrolera:

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

Z drugiej strony, jeśli chcesz zezwolić użytkownikowi na modyfikację tego modelu, będziesz musiał dołączyć odpowiednie pola wejściowe dla każdego pola swojego modelu, które chcesz wysłać na serwer:

@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" />
}

a następnie będziesz miał domyślny segregator modelu zrekonstruować ten model z żądania:

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
    ...
}
Darin Dimitrov
źródło
1
Otrzymuję filejako nulli też Request.Files.Countwynosi 0, czy byłaby jakaś różnica, jeśli formjest AjaxFormi są routeValuesrównież?
bjan
8

Rozwiązany

Model

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

Kontroler

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

I Zobacz

@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" />
}

Uwaga: tytuł parametru z akcji kontrolera musi być zgodny z nazwą elementów wejściowych IEnumerable<HttpPostedFileBase> fileUpload->name="fileUpload[0]"

fileUpload musi pasować

isxaker
źródło
2
To jedyne rozwiązanie, które znalazłem dla wielu plików. Dzięki za udostępnienie kodu.
Rojan Gh.
6

Jeśli nie zawsze będziesz mieć obrazy publikowane w swojej akcji, możesz zrobić coś takiego:

[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
źródło
1

W przypadku wielu plików; zwróć uwagę na nowszą „ wielokrotność atrybut ” dla danych wejściowych:

Formularz:

@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"  />
}

Kontroler:

[HttpPost]
public ActionResult FileImport(IEnumerable<HttpPostedFileBase> files)
{
    return View();
}
mcfea
źródło
1

Pierwsze pobranie pliku jquery.form.js z poniższego adresu URL

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

Napisz poniższy kod w 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>

Metoda działania: -

 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
źródło