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

Posted

技术标签:

【中文标题】如何在 asp.net core 中上传文件?【英文标题】:How to upload files in asp.net core? 【发布时间】:2016-02-13 11:31:54 【问题描述】:

如何使用带有一些模型数据的 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

【问题讨论】:

好像这是最近发布的-> docs.microsoft.com/en-us/aspnet/core/mvc/models/… 【参考方案1】:

您可以将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);
    

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

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

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

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

你应该存储什么?

您应该存储上面生成的唯一文件名(我们在上面使用的uniqueFileName 变量)来存储文件名。当您想将图像显示回来时,您可以使用此值(文件名)并构建图像的 url。

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

@
    var imgFileName = "cats_46df.png";

<img src="~/uploads/@imgFileName"  />

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

<img src="~/uploads/@Model.FileName"  />

将图像存储到表格中

如果你想将文件作为 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");

【讨论】:

嗨 Shyju,我尝试了上面的示例,但对我没有用。图像作为 null 到达 CreatePost 对象中的 Create 方法(其他属性已正确填充)。我会继续调查这个问题,如果我找到任何东西,我会告诉你的。如果您有任何建议,请告诉我。 您的表单有enctype="multipart/form-data" 吗? 这个解决方案对我不起作用,如果我将enctype="multipart/form-data" 添加到我的表单中。知道可能是什么问题吗? IFormFile 始终为空。 检查您的资源是否有set;。还要确保输入文件名与您的属性名称匹配。 使用上面的代码,我发现在使用FileMode.Create 后关闭文件很有帮助,否则会创建一个 .net 正在使用的 0kb 文件,直到我停止调试 var newfile = new FileStream(filePath, FileMode.CreateNew); file.CopyTo(newfile); newfile.Close();【参考方案2】:
 <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】:

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

【讨论】:

注意:如果你想在你的服务或业务层中使用IWebHostEnvironment,那么你需要安装Microsoft.AspNetCore.Http.Features。如果您收到以下异常:Error CS0246 The type or namespace name 'IWebHostEnvironment' could not be found (are you missing a using directive or an assembly reference?),请在您的项目中包含此内容:。来源:github.com/dotnet/Scaffolding/issues/1186【参考方案4】:

你可以试试下面的代码

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);
         _context.SaveChanges();
                 

      return RedirectToAction("Index","Home");   
    

【讨论】:

@BerBar 请添加“索引”操作。此代码不返回。只有工作重定向到另一个动作。【参考方案5】:

控制器代码:-

 public class HomeController : Controller

    private readonly ILogger<HomeController> _logger;

    private IHostingEnvironment _environment;
    public HomeController(ILogger<HomeController> logger,IHostingEnvironment environment)
    
        _logger = logger;
        _environment = environment;
    

    public IActionResult Index()
    
        return View();
    
    [HttpPost]
    public IActionResult uploader()
    
        var filelist = HttpContext.Request.Form.Files;
        if(filelist.Count>0)
        
            foreach(var file in filelist)
            

            var uploads = Path.Combine(_environment.WebRootPath, "files");
            string FileName = file.FileName;
            using (var fileStream = new FileStream(Path.Combine(uploads, FileName), FileMode.Create))
            
                file.CopyToAsync(fileStream);
                                
            
        
        return View("Index");
    
  

查看代码:-

@using (Html.BeginForm("uploader", "Home", FormMethod.Post, new  enctype = "multipart/form-data" ))
     
    <input type="file" multiple name="file" />
    <input type="submit" value="Upload" />

How to upload files in asp.net core

【讨论】:

以上是关于如何在 asp.net core 中上传文件?的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core Web API 中上传文件和 JSON

在 ASP.NET Core 1.0 上处理大文件上传

在ASP.NET Core 中上传文件

Asp.net Core-在使用 javascript 或 C# 上传之前选择和验证 excel 文件?

在 ASP.NET Core 中上传文件

ASP.NET Core 文件上传 之 文件签名验证