且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-15 19:00:44

您可以将 IFormFile 类型的新属性添加到您的视图模型

You can add a new property of type IFormFile to your view model

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

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

and in your GET action method, we will create an object of this view model and send to the view.

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

现在在你的创建视图中,它是强类型到我们的视图模型,有一个 form 标签,它的 enctype 属性设置为 "multipart/form-数据"

Now in your Create view which is strongly typed to our view model, have a form tag which has the enctype attribute set to "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 操作

And your HttpPost action to handle the form posting

[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 路径.这是一个工作示例.

If you want to upload the file to some directory in your app, you should use IHostingEnvironment to get the webroot path. Here is a working sample.

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 生成的随机文件名(以防止覆盖同名文件)

This will save the file to uploads folder inside wwwwroot directory of your app with a random file name generated using Guids ( to prevent overwriting of files with same name)

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

Here we are using a very simple GetUniqueName method which will add 4 chars from a guid to the end of the file name to make it somewhat unique. You can update the method to make it more sophisticated as needed.

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

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

No. Do not store the full url to the image in the database. What if tomorrow your business decides to change your company/product name from www.thefacebook.com to www.facebook.com ? Now you have to fix all the urls in the table!

你应该存储什么?

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

You should store the unique filename which you generated above(the uniqueFileName varibale we used above) to store the file name. When you want to display the image back, you can use this value (the filename) and build the url to the image.

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

For example, you can do this in your view.

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

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

I just hardcoded an image name to imgFileName variable and used that. But you may read the stored file name from your database and set to your view model property and use that. Something like

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

将图像存储到表格中

如果你想将文件作为 bytearray/varbinary 保存到你的数据库中,你可以像这样将 IFormFile 对象转换为字节数组

If you want to save the file as bytearray/varbinary to your database, you may convert the IFormFile object to byte array like this

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

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

Now in your http post action method, you can call this method to generate the byte array from IFormFile and use that to save to your table. the below example is trying to save a Post entity object using entity framework.

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