欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Asp.Net Core 轻松学-一行代码搞定文件上传

程序员文章站 2023-11-15 23:42:58
在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能;通过创建自定义绑定模型来实现文件上传。 ......

前言

    在 web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能;通过创建自定义绑定模型来实现文件上传。

1. 实现自定义绑定模型
  • 1.1 在 asp.net core mvc 中,内置了很多种绑定模型,让我们可以很方便的去使用,比如下面常用的几种绑定模型
 frombodyattribute
 fromfromattribute
 fromqueryattribute
 fromheaderattribute
 fromservicesattribute
 fromrouteattribute
  • 常见用法比如
    [httppost]
     public async task<iactionresult> postinfo([frombody]userinfo user,[fromquery] string city)
    {
        ...
    }
    1. 查看以上绑定模型,唯独缺少一个 fromfileattribute ,下面就来实现一个自己的 fromfileattribute
    public class fromfileattribute : attribute, ibindingsourcemetadata
    {
        public bindingsource bindingsource => bindingsource.formfile;
    }
  • 非常简单,就三行代码,完全照抄系统内置的绑定模型,唯一不同的就是指定 bindingsource 为 bindingsource.formfile。
2. 实现一个上传文件实体类,专门用于接收客户端参数
  • 2.1 创建 userfile
public class userfile
    {
        public string filename { get; set; }
        public long length { get; set; }
        public string extension { get; set; }
        public string filetype { get; set; }

        private readonly static string[] filters = { ".jpg", ".png", ".bmp" };
        public bool isvalid => !string.isnullorempty(this.extension) && filters.contains(this.extension);

        private iformfile file;
        public iformfile file
        {
            get { return file; }
            set
            {
                if (value != null)
                {
                    this.file = value;

                    this.filetype = this.file.contenttype;
                    this.length = this.file.length;
                    this.extension = this.file.filename.substring(file.filename.lastindexof('.'));
                    if (string.isnullorempty(this.filename))
                        this.filename = this.filename;
                }
            }
        }

        public async task<string> saveas(string destinationdir = null)
        {
            if (this.file == null)
                throw new argumentnullexception("没有需要保存的文件");

            if (destinationdir != null)
                directory.createdirectory(destinationdir);

            var newname = datetime.now.ticks;
            var newfile = path.combine(destinationdir ?? "", $"{newname}{this.extension}");
            using (filestream fs = new filestream(newfile, filemode.createnew))
            {
                await this.file.copytoasync(fs);
                fs.flush();
            }

            return newfile;
        }
    }
  • userfile 是一个带保持文件行为的实体类,该类的公共属性用于从表单域中接收和属性名称相同的表单值,其中公共属性 file 用于接收文件,并在设置值的时候去做一些其它属性初始化的工作,比如文件长度和扩展名、文件类型
  • 其中还实现了一个简单的文件过滤器,判断客户端上传的文件是否属于服务端允许上传的文件扩展名
  • 最后 saveas(string destinationdir = null) 通过传入指定目录,将文件保存,并返回保存后的文件绝对路径
3. 上传文件
  • 3.1 下面就定义一个简单的 api 接口,用于测试上传文件
        [httppost]
        public async task<iactionresult> post([fromfile]userfile file)
        {
            if (file == null || !file.isvalid)
                return new jsonresult(new { code = 500, message = "不允许上传的文件类型" });

            string newfile = string.empty;
            if (file != null)
                newfile = await file.saveas("/data/files/images");

            return new jsonresult(new { code = 0, message = "成功", url = newfile });
        }
  • 3.2 首先是在 post([fromfile]userfile file) 中使用上面创建的 fromfileattribute 对模型 userfile 进行绑定,然后验证文件是否正确,接下来通过 file.saveas("/data/files/images"); 保存文件

  • 3.3 上传代码非常简单,几乎到了无法精简的程度,最终发挥作用的就是 file.saveas 操作

4. 上传测试
  • 4.1 现在通过控制台启动服务

Asp.Net Core 轻松学-一行代码搞定文件上传

  • 4.2 使用 postman 模拟表单上传文件

Asp.Net Core 轻松学-一行代码搞定文件上传

  • 4.3 上传成功,现在来查看目录下是否有文件

Asp.Net Core 轻松学-一行代码搞定文件上传

结语
  • 在上传表单中,我们定义了附件的名称为 file 对应绑定模型的公共属性 file,这样模型就可以自动获得该文件
  • 表单中还传递了另外一个字段 filename,对应绑定模型的公共属性 filename,实现自定义文件友好显示名称
  • 通过自定义模型绑定,实现了快速上传文件功能,该功能只能用于上传小文件,对于大文件,还是需要实现分片上传,或者使用 cdn 等服务商的接口
示例代码下载

https://files.cnblogs.com/files/viter/ron.uploadfile.zip