web-dev-qa-db-fra.com

ASP.NET MVC 4 C # HttpPostedFileBase, comment stocker un fichier

Modèle

public partial class Assignment
{
    public Assignment()
    {
        this.CourseAvailables = new HashSet<CourseAvailable>();
    }

    public string AssignmentID { get; set; }
    public Nullable<System.DateTime> SubmissionDate { get; set; }
    public string Status { get; set; }
    public Nullable<decimal> Mark { get; set; }
    public string Comments { get; set; }
    public string FileLocation  { get; set; }
    public virtual ICollection<CourseAvailable> CourseAvailables { get; set; }
}}

Manette

 public ActionResult Create(Assignment assignment)
    {
        if (ModelState.IsValid)
        {


            db.Assignments.Add(assignment);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(assignment);
    }

Vue

<div class="editor-field">
    <%: Html.TextBoxFor(model => model.FileLocation, new { type="file"})%>
    <%: Html.ValidationMessageFor(model => model.FileLocation) %>
</div>

Comment puis-je stocker un fichier si je voulais stocker le fichier dans le dossier serveur/chemin et dans la base de données que je veux seulement stocker le nom/chaîne du chemin.

6
WeakTaenie

vous pouvez télécharger un fichier et enregistrer son URL dans la table de la base de données, comme suit:

Vue:

@using(Html.BeginForm("Create","Assignment",FormMethod.Post,new {enctype="multipart/form-data"}))
{
    ...
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.FileLocation, new { type="file"})%>
        <%: Html.ValidationMessageFor(model => model.FileLocation) %>
    </div>
    ...
}

Action:

[HttpPost]
public ActionResult Create(Assignment assignment)
{
    if (ModelState.IsValid)
    {
        if(Request.Files.Count > 0)
        {
            HttpPostedFileBase file = Request.Files[0];
            if (file.ContentLength > 0) 
            {
                var fileName = Path.GetFileName(file.FileName);
                assignment.FileLocation = Path.Combine(
                    Server.MapPath("~/App_Data/uploads"), fileName);
                file.SaveAs(assignment.FileLocation);
            }
            db.Assignments.Add(assignment);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    }

    return View(assignment);
}

Détails:

Pour une meilleure compréhension, consultez ce bon article Téléchargement d’un fichier (ou de fichiers) avec ASP.NET MVC

17
Ehsan Sajjad

Voici comment je l'ai fait:

View.cs

<div class="row">

    @using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <input type="file" name="FileUpload" id="FileUpload" runat="server" />
        <input type="submit" value="Save" class="btn btn-default" />
    }

</div>

J'utilisais HomeController, vous créez donc la fonction Upload ici. J'indique également comment vous pouvez stocker le contenu du fichier dans la base de données, pas seulement l'emplacement, et le code ci-dessous utilise le modèle Assignment fourni, mais je vais également montrer comment je l'ai enregistré dans la base de données dans mon dossier. case avec un modèle que j'ai créé pour ma table, ITEM_ATCHMT.

Vous ne devriez pas avoir à transmettre de modèle et à le renvoyer si tout ce que vous avez est un contrôle FileUpload sur la page et si les données ne sont pas renseignées dans la vue, cette fonction ne le fait pas, et ma vue ne N'utilisez pas de modèle - le vôtre peut être différent et vous pouvez souhaiter que votre modèle soit transmis, renvoyé, s'il est utilisé dans votre vue.

J'ai configuré le mien pour que plusieurs objets soient affichés en même temps. J'avais donc un List<ViewDataUploadFilesResult> qui recevait leurs données et qui serait itéré dans le processus de sauvegarde de chacun des fichiers et de leurs métadonnées dans la base de données. Vous pouvez l'utiliser pour simplement sauvegarder un fichier à la fois. J'ai donc ajouté le code correspondant et commenté les parties des multiples fichiers. Espérons que cela ne dérange personne - juste deux façons différentes de faire la même chose, au final.

HomeController.cs

    [HttpPost]
    public ActionResult Upload()
    {
        //var r = new List<ViewDataUploadFilesResult>();
        var r = new ViewDataUploadFilesResult();
        Assignment a = new Assignment();

        if (ModelState.IsValid)
        {
            if (Request.Files.Count > 0)
            {
                HttpPostedFileBase file = Request.Files[0];
                if (file.ContentLength > 0)
                {
                    int fileSize = file.ContentLength;
                    var fileName = Path.GetFileName(file.FileName);

                    //You could do this to get the content -
                    //it would need a varbinary(max) field 
                    //Stream posted file into a byte array
                    byte[] fileByteArray = new byte[fileSize];
                    file.InputStream.Read(fileByteArray, 0, fileSize);

                    //Uploading properly formatted file to server.
                    string fileLocation = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
                    if (!Directory.Exists(Server.MapPath("~/App_Data/uploads")))
                        Directory.CreateDirectory(Server.MapPath("~/App_Data/uploads"));
                    file.SaveAs(fileLocation);

                    // I used a ViewModel to collect my file information
                    ViewDataUploadFilesResult r = new ViewDataUploadFilesResult();
                    r.Name = fileName;
                    r.FilePath = fileLocation;
                    r.Length = fileSize;
                    r.FileObj = file;
                    r.Content = fileByteArray;

                    // I provided a list so I could upload multiple files
                    // at once, but you might've just had the one item, above
                    //r.Add(new ViewDataUploadFilesResult()
                    //{
                    //    Name = fileName,
                    //    FilePath = fileLocation,
                    //    Length = fileSize,
                    //    FileObj = file,
                    //    Content = fileByteArray
                    //});

                    // Below is for singular ViewDataUploadFilesResult objects (uncomment the loop for multiple)
                    //for (int i = 0; i < r.Count; i++)
                    //{
                        //assignment.FileLocation = r[i].FilePath; //multiple objects need an index, [i]
                        assignment.FileLocation = r.FilePath;  //singular objects don't
                        assignment.Status = "Uploaded";
                        assignment.Comments = "Completed";
                    //}

                    // You also could've just not used ViewDataUploadFilesResult 
                    // at all, and just used assignment, only
                    // and just added fileSize, fileContents, etc. to it

                    EFModel db = new EFModel();  // this is your Entity Framework context
                    db.Assignments.Add(assignment);  //"Assignments" would be your table
                    db.SaveChanges();

                }

                return RedirectToAction("Index");
                //return View("Index", r);
            }
        }

        return View();
    }

Modèle supplémentaire

ViewDataUploadFilesResult.cs

public class ViewDataUploadFilesResult
{
    public string Name { get; set; }
    public string FilePath { get; set; }
    public int Length { get; set; }
    public HttpPostedFileBase FileObj { get; set; }
    public byte[] Content { get; set; }
}

Pour moi, au lieu d’utiliser tout ce ViewModel, c’est un modèle réel pour ma table Attachments:

public partial class ITEM_ATCHMT
{
    [Key]
    public Guid ATCHMT_ID { get; set; }

    public int ITEM_ID { get; set; }

    [ForeignKey("ITEM_ID")]
    public virtual ITEM item { get; set; }

    [Required]
    [StringLength(50)]
    public string USER_NAME_DESC { get; set; }

    [Required]
    [StringLength(250)]
    public string FILE_NAME_TXT { get; set; }

    [Required]
    public byte[] FILE_CNTNT_CD { get; set; }

    [Required]
    [StringLength(10)]
    public string FILE_TYPE_DESC { get; set; }

    public DateTime CREATED_DT { get; set; }
} 

Et dis que je voulais l'associer à cet article:

public partial class ITEM
{
    [Key]
    public int ITEM_ID { get; set; }

    [Required]
    [StringLength(50)]
    public string NAME { get; set; }

}

Pour enregistrer des données à l'aide d'Entity Framework, il vous suffit de remplir ce modèle, puis de faire une .SaveChanges() sur votre contexte:

EFModel db = new EFModel();  // this is my Entity Framework context
ITEM item = new ITEM();
item.NAME = "My Item";

db.ITEM.Add(item);  //"ITEM" is my table and name of an EF model, "item" is the object that represents my model
db.SaveChanges();

Et si ITEM_ID est configuré avec l'incrémentation automatique:

ITEM_ATCHMT atchmt_model = new ITEM_ATCHMT();
atchmt_model.ATCHMT_ID = Guid.NewGuid();
atchmt_model.ITEM_ID = item.ITEM_ID // <-- this should have the ID
atchmt_model.USER_NAME_DESC = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
atchmt_model.FILE_CNTNT_CD = r.Content;
atchmt_model.FILE_NAME_TXT = r.Name;
atchmt_model.FILE_TYPE_DESC = r.Name.Split('.')[1];
atchmt_model.CREATED_DT = DateTime.Now;

db.ITEM_ATCHMT.Add(atchmt_model);  //"ITEM_ATCHMT" is my table
db.SaveChanges();

 enter image description here

0
vapcguy