如何在asp.net核心中上传文件?

时间:2016-02-13 11:31:54

标签: c# file-upload asp.net-core-mvc image-manipulation

如何使用Asp.net MVC 6上传文件或图像以及一些模型数据? 例如,我有一个这样的表格;

<form>
    <input type="file">
    <input type="text" placeholder="Image name...">
    <input type="text" placeholder="Image description...">
    <input type="submit" value="Submit">
</form>

我阅读了很多关于如何上传的教程,但是我没有看到上传的内容与上面的表格一样的数据。

此外,是否存在用于重新调整大小和图像水印的图像处理库,与Codeigniter图像处理类相同? (https://codeigniter.com/user_guide/libraries/image_lib.html

4 个答案:

答案 0 :(得分:49)

您可以向视图模型中添加IFormFile类型的新属性

public class CreatePost
{
   public string ImageCaption { set;get; }
   public string ImageDescription { set;get; }
   public IFormFile MyImage { set; get; }
}

在您的GET操作方法中,我们将创建此视图模型的对象并发送到视图。

public IActionResult Create()
{
   return View(new CreatePost());
}

现在,在我们的视图模型中强类型的“创建”视图中,有一个form标记,其enctype属性设置为"multipart/form-data"

@model CreatePost
<form asp-action="Create" enctype="multipart/form-data">   

    <input asp-for="ImageCaption"/>
    <input asp-for="ImageDescription"/>
    <input asp-for="MyImage"/>

    <input type="submit"/>
</form>

您的HttpPost操作处理表单发布

[HttpPost]
public IActionResult Create(CreatePost model)
{
   var img = model.MyImage;
   var imgCaption = model.ImageCaption;

   //Getting file meta data
   var fileName = Path.GetFileName(model.MyImage.FileName);
   var contentType = model.MyImage.ContentType;

   // do something with the above data
   // to do : return something
}

如果要将文件上传到应用中的某个目录,则应使用IHostingEnvironment获取webroot路径。这是一个工作样本。

public class HomeController : Controller
{
    private readonly IHostingEnvironment hostingEnvironment;
    public HomeController(IHostingEnvironment environment)
    {
        hostingEnvironment = environment;
    }
    [HttpPost]
    public IActionResult Create(CreatePost model)
    {
        // do other validations on your model as needed
        if (model.MyImage != null)
        {
            var uniqueFileName = GetUniqueFileName(model.MyImage.FileName);
            var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
            var filePath = Path.Combine(uploads,uniqueFileName);
            model.MyImage.CopyTo(new FileStream(filePath, FileMode.Create)); 

            //to do : Save uniqueFileName  to your db table   
        }
        // to do  : Return something
        return RedirectToAction("Index","Home");
    }
    private string GetUniqueFileName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return  Path.GetFileNameWithoutExtension(fileName)
                  + "_" 
                  + Guid.NewGuid().ToString().Substring(0, 4) 
                  + Path.GetExtension(fileName);
    }
}

这会将文件保存到应用程序uploads目录下的wwwwroot文件夹中,并使用Guids生成随机文件名(以防止覆盖同名文件)

这里我们使用一个非常简单的GetUniqueName方法,它将guid中的4个字符添加到文件名的末尾,使其有点独特。您可以根据需要更新方法以使其更复杂。

您是否应该将完整的网址存储到数据库中的上传图片?

没有。不要将完整的URL存储到数据库中的映像中。如果明天您的公司决定将您的公司/产品名称从www.thefacebook.com更改为www.facebook.com,该怎么办?现在你必须修复表中的所有网址!

你应该存储什么?

您应该存储上面生成的唯一文件名(我们上面使用的uniqueFileName varibale )来存储文件名。当您想要显示图像时,您可以使用此值(文件名)并为图像构建网址。

例如,您可以在视图中执行此操作。

@{
    var imgFileName = "cats_46df.png";
}
<img src="~/uploads/@imgFileName"  alt="my img"/>

我只是将图片名称硬编码为imgFileName变量并使用它。但是,您可以从数据库中读取存储的文件名,并将其设置为视图模型属性并使用它。像

这样的东西
<img src="~/uploads/@Model.FileName"  alt="my img"/>

将图像存储到表格

如果要将文件保存为bytearray / varbinary到数据库,可以将IFormFile对象转换为字节数组,如下所示

private byte[] GetByteArrayFromImage(IFormFile file)
{
    using (var target = new MemoryStream())
    {
        file.CopyTo(target);
        return target.ToArray();
    }
}

现在,在http post action方法中,您可以调用此方法从IFormFile生成字节数组,并使用它保存到表中。以下示例尝试使用实体框架保存Post实体对象。

[HttpPost]
public IActionResult Create(CreatePost model)
{
    //Create an object of your entity class and map property values
    var post=new Post() { ImageCaption = model.ImageCaption };

    if (model.MyImage != null)
    {
       post.Image =  GetByteArrayFromImage(model.MyImage);
    }
    _context.Posts.Add(post);
    _context.SaveChanges();
    return RedirectToAction("Index","Home");
}

答案 1 :(得分:2)

Fileservice.cs

public class FileService : IFileService
{
    private readonly IWebHostEnvironment env;

    public FileService(IWebHostEnvironment env)
    {
        this.env = env;
    }

    public string Upload(IFormFile file)
    {
        var uploadDirecotroy = "uploads/";
        var uploadPath = Path.Combine(env.WebRootPath, uploadDirecotroy);

        if (!Directory.Exists(uploadPath))
            Directory.CreateDirectory(uploadPath);

        var fileName = Guid.NewGuid() + Path.GetExtension(file.FileName);
        var filePath = Path.Combine(uploadPath, fileName);

        using (var strem = File.Create(filePath))
        {
            file.CopyTo(strem);
        }
        return fileName;
    }
}

IFileService

namespace studentapps.Services
{
    public interface IFileService
    {
        string Upload(IFormFile file);
    }
}

StudentController

[HttpGet]
public IActionResult Create()
{
    var student = new StudentCreateVM();
    student.Colleges = dbContext.Colleges.ToList();
    return View(student);
}

[HttpPost]
public IActionResult Create([FromForm] StudentCreateVM vm)
{
    Student student = new Student()
    {
        DisplayImage = vm.DisplayImage.FileName,
        Name = vm.Name,
        Roll_no = vm.Roll_no,
        CollegeId = vm.SelectedCollegeId,
    };


    if (ModelState.IsValid)
    {
        var fileName = fileService.Upload(vm.DisplayImage);
        student.DisplayImage = fileName;
        getpath = fileName;

        dbContext.Add(student);
        dbContext.SaveChanges();
        TempData["message"] = "Successfully Added";
    }
    return RedirectToAction("Index");
}

答案 2 :(得分:0)

 <form class="col-xs-12" method="post" action="/News/AddNews" enctype="multipart/form-data">

     <div class="form-group">
        <input type="file" class="form-control" name="image" />
     </div>

     <div class="form-group">
        <button type="submit" class="btn btn-primary col-xs-12">Add</button>
     </div>
  </form>

我的行动是

        [HttpPost]
        public IActionResult AddNews(IFormFile image)
        {
            Tbl_News tbl_News = new Tbl_News();
            if (image!=null)
            {

                //Set Key Name
                string ImageName= Guid.NewGuid().ToString() + Path.GetExtension(image.FileName);

                //Get url To Save
                string SavePath = Path.Combine(Directory.GetCurrentDirectory(),"wwwroot/img",ImageName);

                using(var stream=new FileStream(SavePath, FileMode.Create))
                {
                    image.CopyTo(stream);
                }
            }
            return View();
        }

答案 3 :(得分:-1)

你可以尝试下面的代码

1-模型或视图模型

public class UploadImage 
{
  public string ImageFile { get; set; }
  public string ImageName { get; set; }
  public string ImageDescription { get; set; }
}

2-查看页面

<form class="form-horizontal" asp-controller="Image" asp-action="UploadImage" method="POST" enctype="multipart/form-data">

<input type="file" asp-for="ImageFile">
<input type="text" asp-for="ImageName">
<input type="text" asp-for="ImageDescription">
</form>

3-控制器

 public class Image
    {

      private IHostingEnvironment _hostingEnv;
      public Image(IHostingEnvironment hostingEnv)
      {
         _hostingEnv = hostingEnv;
      }

      [HttpPost]
      public async Task<IActionResult> UploadImage(UploadImage model, IFormFile ImageFile)
      {
        if (ModelState.IsValid)
         {
        var filename = ContentDispositionHeaderValue.Parse(ImageFile.ContentDisposition).FileName.Trim('"');
        var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", ImageFile.FileName);
        using (System.IO.Stream stream = new FileStream(path, FileMode.Create))
         {
            await ImageFile.CopyToAsync(stream);
         }
          model.ImageFile = filename;
         _context.Add(model);
         }        
      }        
    }