博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper
阅读量:6956 次
发布时间:2019-06-27

本文共 7465 字,大约阅读时间需要 24 分钟。

 

前言

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

1. 实现自定义绑定模型
  • 1.1 在 Asp.Net Core MVC 中,内置了很多种绑定模型,让我们可以很方便的去使用,比如下面常用的几种绑定模型
FromBodyAttribute FromFromAttribute FromQueryAttribute FromHeaderAttribute FromServicesAttribute FromRouteAttribute
  • 常见用法比如
[HttpPost]     public async Task
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
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
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 现在通过控制台启动服务

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

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

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

 

 

 

 

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Text;
using System.Web.Script.Serialization;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<br><br>[Serializable]
    
public 
static 
class 
JSONHelper
    
{
        
/// <summary>
        
/// 对象转JSON
        
/// </summary>
        
/// <param name="obj">对象</param>
        
/// <returns>JSON格式的字符串</returns>
        
public 
static 
string 
ObjectToJSON(
object 
obj)
        
{
            
JavaScriptSerializer jss = 
new 
JavaScriptSerializer();
            
try
            
{
                
return 
jss.Serialize(obj);
            
}
            
catch 
{ }
            
return 
null
;
        
}
 
        
/// <summary>
        
///
        
/// JSON文本转对象,泛型方法
        
/// </summary>
        
/// <typeparam name="T">类型</typeparam>
        
/// <param name="jsonText">JSON文本</param>
        
/// <returns>指定类型的对象</returns>
        
public 
static 
T JSONToObject<T>(
string 
jsonText)
        
{
            
JavaScriptSerializer jss = 
new 
JavaScriptSerializer();
            
try
            
{
                
return 
jss.Deserialize<T>(jsonText);
            
}
            
catch
{}
            
return 
default
(T);
        
}
 
        
public 
static 
string 
ObjectToJsonDateTime(
object 
obj)
        
{
            
JavaScriptSerializer jss = 
new 
JavaScriptSerializer();
            
jss.RegisterConverters(
new 
JavaScriptConverter[] { 
new 
DateTimeConverter() });
            
try
            
{
                
return 
jss.Serialize(obj);
            
}
            
catch 
{ }
            
return 
null
;
        
}
    
}<br><br><br>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using 
System;
using 
System.Collections;
using 
System.Collections.Generic;
using 
System.Linq;
using 
System.Text;
using 
System.Web.Script.Serialization;
     
 
 
public 
class 
DateTimeConverter : JavaScriptConverter
    
{
        
public 
override 
object 
Deserialize(IDictionary<
string
object
> dictionary, Type type, JavaScriptSerializer serializer)
        
{
            
return 
new 
JavaScriptSerializer().ConvertToType(dictionary, type);
        
}
 
        
public 
override 
IDictionary<
string
object
> Serialize(
object 
obj, JavaScriptSerializer serializer)
        
{
            
if 
(!(obj 
is 
DateTime))
            
{
                
return 
null
;
            
}
            
return 
new 
CustomString(((DateTime)obj).ToString(
"yyyy-MM-dd HH:mm:ss"
));
        
}
 
        
public 
override 
IEnumerable<Type> SupportedTypes
        
{
            
get
            
{
                
return 
new
[] { 
typeof
(DateTime) };
            
}
        
}
 
        
private 
class 
CustomString : Uri, IDictionary<
string
object
>
        
{
            
public 
CustomString(
string 
str) : 
base
(str, UriKind.Relative)
            
{
            
}
 
            
void 
IDictionary<
string
object
>.Add(
string 
key, 
object 
value)
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
bool 
IDictionary<
string
object
>.ContainsKey(
string 
key)
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
ICollection<
string
> IDictionary<
string
object
>.Keys
            
{
                
get
                
{
                    
throw 
new 
NotImplementedException();
                
}
 
            
}
 
            
bool 
IDictionary<
string
object
>.Remove(
string 
key)
            
{
                
throw 
new 
NotImplementedException();
            
}
 
 
            
bool 
IDictionary<
string
object
>.TryGetValue(
string 
key, 
out 
object 
value)
            
{
                
throw 
new 
NotImplementedException();
 
            
}
 
            
ICollection<
object
> IDictionary<
string
object
>.Values
            
{
 
                
get
                
{
                    
throw 
new 
NotImplementedException();
                
}
 
            
}
 
            
object 
IDictionary<
string
object
>.
this
[
string 
key]
            
{
                
get
                
{
                    
throw 
new 
NotImplementedException();
                
}
                
set
                
{
                    
throw 
new 
NotImplementedException();
                
}
            
}
 
            
void 
ICollection<KeyValuePair<
string
object
>>.Add(KeyValuePair<
string
object
> item)
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
void 
ICollection<KeyValuePair<
string
object
>>.Clear()
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
bool 
ICollection<KeyValuePair<
string
object
>>.Contains(KeyValuePair<
string
object
> item)
            
{
 
                
throw 
new 
NotImplementedException();
 
            
}
 
            
void 
ICollection<KeyValuePair<
string
object
>>.CopyTo(KeyValuePair<
string
object
>[] array, 
int 
arrayIndex)
            
{
                
throw 
new 
NotImplementedException();
 
            
}
 
            
int 
ICollection<KeyValuePair<
string
object
>>.Count
            
{
                
get
                
{
                    
throw 
new 
NotImplementedException();
                
}
            
}
 
            
bool 
ICollection<KeyValuePair<
string
object
>>.IsReadOnly
            
{
                
get
                
{
                    
throw 
new 
NotImplementedException();
                
}
            
}
 
            
bool 
ICollection<KeyValuePair<
string
object
>>.Remove(KeyValuePair<
string
object
> item)
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
IEnumerator<KeyValuePair<
string
object
>> IEnumerable<KeyValuePair<
string
object
>>.GetEnumerator()
            
{
                
throw 
new 
NotImplementedException();
            
}
 
            
IEnumerator IEnumerable.GetEnumerator()
            
{
                
throw 
new 
NotImplementedException();
            
}
        
}
    
}

  

转载地址:http://ldmil.baihongyu.com/

你可能感兴趣的文章
变量替换删除企业应用场景
查看>>
nautilus can't be used now,due to an unexpected error解决方法
查看>>
XenApp/XenDesktop 7.11新功能
查看>>
全面降低windows系统的安全隐患(一)[Web安全大家谈]
查看>>
2014年7月14日学习笔记--scriptreplay相关操作
查看>>
openstack resize 中遇到的问题
查看>>
AD-删除账户命令 Remove-ADUser
查看>>
第九单元练习题
查看>>
scponly 密钥无密码scp登录
查看>>
重置otrs登录密码
查看>>
CentOS下搭建SVN服务器
查看>>
#15、#16 网络的基本构成与网络的几协议
查看>>
视频客户端电脑版去广告补丁V 1.0
查看>>
HTTP 499 状态码 nginx下 499错误
查看>>
shell 九九乘法表
查看>>
接口调用-http和https
查看>>
undo backup optimization does not work on 11.2.0.1?
查看>>
F5 的SNAT的irules相关配置
查看>>
安装redis(3.2.9)
查看>>
shell脚本之一
查看>>