ASP.NET MVC 4 C# HttpPostedFileBase, How do I Store File

后端 未结 3 990
醉酒成梦
醉酒成梦 2020-11-27 06:23

Model

public partial class Assignment
{
    public Assignment()
    {
        this.CourseAvailables = new HashSet();
         


        
3条回答
  •  刺人心
    刺人心 (楼主)
    2020-11-27 06:28

    Here's how I did it:

    View.cs

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

    I was using HomeController, so you create the Upload function there. I'm also including how you might store the file contents in the database, not just the location, and the code below makes use of the Assignment model that was provided, but I'll also show how I saved it to the database in my case with a model I created for my table, ITEM_ATCHMT.

    You shouldn't have to pass in a model & pass it back if all you have is a FileUpload control on the page and aren't populating data on the view with it, so this function doesn't do that, and my View doesn't use a model - yours may be different and you may want to keep your model being passed in, returned, if used on your view.

    I set mine up for multiple objects to be posted at one time, so I had a List that received their data and would get iterated through in the process of saving each of the files and their metadata to the database. You could use it to simply save one file at a time, though, so I've added the code for that and commented out the parts for the multiple files. Hopefully it doesn't confuse anyone - just 2 different ways of doing the same thing, in the end.

    HomeController.cs

        [HttpPost]
        public ActionResult Upload()
        {
            //var r = new List();
            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();
        }
    

    Additional Model

    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; }
    }
    

    For me, instead of using this whole ViewModel, this is an actual model for my Attachments table:

    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; }
    } 
    

    And say I wanted to associate it with this item:

    public partial class ITEM
    {
        [Key]
        public int ITEM_ID { get; set; }
    
        [Required]
        [StringLength(50)]
        public string NAME { get; set; }
    
    }
    

    To save any data using Entity Framework, you just need to fill that model, then do a .SaveChanges() on your context:

    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();
    

    And if ITEM_ID is set up with auto-incrementing:

    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();
    

提交回复
热议问题