.Net Web API 005 Controller上传小文件
1、附属文件对象定义
一般情况下,系统里面的文件都会附属一个对象存在,例如用户的头像文件,会附属用户对象存在。邮件中的文件会附属邮件存在。所以在系统里面,我们会创建一个附属文件对象,命名为AttachedFileEntity。其定义如下所示。
/// <summary>
/// 附属文件实体对象
/// </summary>
public class AttachedFileEntity
{ /// <summary>
/// 实体对象GUID
/// </summary>
public string GUID { get; set; } = ""; /// <summary>
/// 所属对象的GUID
/// </summary>
public string EntityGUID { get; set; } = ""; /// <summary>
/// 名称
/// </summary>
public string Name { get; set; } = ""; /// <summary>
/// 关键字
/// </summary>
public string KeyWord { get; set; } = ""; /// <summary>
/// 文件大小
/// </summary>
public int FileSize { get; set; } = 0; /// <summary>
/// 服务器存储路径
/// </summary>
public string ServerPath { get; set; } = ""; /// <summary>
/// 描述信息
/// </summary>
public string Description { get; set; } = ""; }
EntityGUID属性的作用是,定义该文件属于哪个实体对象,例如某个用户的头像文件,该属性就是这个用户对象的GUID值。
KeyWord属性用来标识文件。例如UserEntity有两个文件,头像和一个自我介绍的视频文件。这两个文件的EntityGUID都是UserEntity的GUID,那么就可以通过KeyWord来区分两个文件是做什么用的。
2、小文件上传服务
如果一个文件比较小,例如3M以内,那么我们就可以一次性把文件上传上来,上传的时候,要把AttachedFileEntity对象传进来,并添加到数据库中。
代码如下所示。
/// <summary>
/// 上传文件
/// </summary>
/// <param name="pEntity"></param>
/// <returns></returns>
[HttpPost]
[Route("UploadFile")]
public IActionResult UploadFile()
{
//获取客户端传来的数据
var myEntityJosnString = Request.Form["pEntity"].ToString();
var myEntity = JsonSerializer.Deserialize<AttachedFileEntity>(myEntityJosnString);
var myFile = Request.Form.Files[0]; //设置新的文件路径
string myFileEx = Path.GetExtension(myFile.FileName);
string myServerFilePath = DateTime.Now.ToString("yyyy_MM_dd") + "\\" + Guid.NewGuid().ToString() + myFileEx;
myEntity!.ServerPath = myServerFilePath; //创建目录
string myFullServerPath = AppDomain.CurrentDomain.BaseDirectory + "\\Files\\" + myServerFilePath;
string myFullFolder = Path.GetDirectoryName(myFullServerPath)!;
if (Directory.Exists(myFullFolder) == false)
{
Directory.CreateDirectory(myFullFolder);
} Stream? myStream = null;
FileStream? myFileStream = null;
BinaryWriter? myBinaryWriter = null;
try
{
myStream = myFile.OpenReadStream();
byte[] myBytes = new byte[myStream.Length];
myStream.Read(myBytes, 0, myBytes.Length);
myStream.Seek(0, SeekOrigin.Begin); myFileStream = new FileStream(myFullServerPath, FileMode.Create);
myBinaryWriter = new BinaryWriter(myFileStream);
myBinaryWriter.Write(myBytes);
}
finally
{
myBinaryWriter?.Close();
myFileStream?.Close();
myStream?.Close();
} //把附属文件对象保存到数据库中
//代码略 return this.Ok(myEntity);
}
因为我们要传入两个复杂的对象AttachedFileEntity和File,所以就不能用参数接了,就需要用代码从Request里面读取。文件其本质就是二进制数据,我们获取这个二进制之后,把数据保存成文件就可以了。然后把pEntity写入到数据库中。
3、前端调用
先用桌面端测试,界面是用C#写的WPF桌面软件,入下图所示。

调用代码入下所示。
var myFilePath = this.UI_SmallFile_TextBox.Text.Trim();
if (myFilePath.Length == 0)
{
MessageBox.Show("请选择一个文件。");
return;
}
if (File.Exists(myFilePath) == false)
{
MessageBox.Show("文件不存在,请重新选择。");
return;
} //定义AttachedFileEntity
var myAttachedFileEntity = new AttachedFileEntity()
{
GUID = Guid.NewGuid().ToString(),
Name = "用户头像",
KeyWord = "UserProfilePhoto",
Description = "",
EntityGUID = "AAAA"
}; //定义请求内容
var myFileStream = new FileStream(myFilePath, FileMode.Open);
myAttachedFileEntity.FileSize = (int)myFileStream.Length;
var myFileName = Path.GetFileName(myFilePath);
var myFileStreamContent = new StreamContent(myFileStream);
var myMultipartFormDataContent = new MultipartFormDataContent
{
{ JsonContent.Create(myAttachedFileEntity), "pEntity" },
{ myFileStreamContent, "pFormFile", myFileName }
}; //请求服务
var myHttpClientEx = new HttpClientEx(new HttpClient())
{
Url = "http://localhost:5000/api/AttachedFile/UploadFile",
HttpContent = myMultipartFormDataContent
};
await myHttpClientEx.PostAsync();
myFileStream.Close(); //解析结果
if (myHttpClientEx.IsSuccess == false)
{
MessageBox.Show(("上传文件失败," + myHttpClientEx.ResponseContenString));
return;
}
var myEntity = myHttpClientEx.GetResponseObject<AttachedFileEntity>();
var myEntityJosnString = JsonSerializer.Serialize(myEntity);
MessageBox.Show(myEntityJosnString);
HttpClientEx是对.Net定义的HttpClient一些功能的扩展,这样用起来会比较方便,代码定义如下。
/// <summary>
/// HttpClient的自定义扩展类
/// </summary>
public class HttpClientEx
{ /// <summary>
/// HttpClient的自定义扩展类
/// </summary>
/// <param name="pHttpClient"></param>
public HttpClientEx(HttpClient? pHttpClient)
{
this.HttpClient = pHttpClient;
this.ParameterDictionary = new Dictionary<string, string>();
} /// <summary>
/// HttpClient对象
/// </summary>
public HttpClient? HttpClient { get; private set; } /// <summary>
/// 服务地址
/// </summary>
public string Url { get; set; } = ""; /// <summary>
/// 参数字典
/// </summary>
public Dictionary<string, string> ParameterDictionary { get; private set; } /// <summary>
/// 请求内容
/// </summary>
public HttpContent? HttpContent { get; set; } /// <summary>
/// 请求返回的消息
/// </summary>
public HttpResponseMessage? ResponseMessage { get; private set; } /// <summary>
/// 是否执行成功
/// </summary>
public bool IsSuccess { get; private set; } /// <summary>
/// 返回的内容字符串
/// </summary>
public string ResponseContenString { get; private set; } = ""; /// <summary>
/// Get
/// </summary>
/// <returns></returns>
public async Task GetAsync()
{
var myUrlWithParameters = this.GetUrlWithParameters();
this.ResponseMessage = await this.HttpClient!.GetAsync(myUrlWithParameters);
this.IsSuccess = this.ResponseMessage.IsSuccessStatusCode;
this.ResponseContenString = await this.ResponseMessage.Content.ReadAsStringAsync();
} /// <summary>
/// Get
/// </summary>
/// <returns></returns>
public async Task PostAsync()
{
var myUrlWithParameters = this.GetUrlWithParameters();
this.ResponseMessage = await this.HttpClient!.PostAsync(myUrlWithParameters, this.HttpContent);
this.IsSuccess = this.ResponseMessage.IsSuccessStatusCode;
this.ResponseContenString = await this.ResponseMessage.Content.ReadAsStringAsync();
} /// <summary>
/// 得到返回的对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T? GetResponseObject<T>()
{
if (this.ResponseContenString == "")
{
return default;
}
var myJsonSerializerOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
};
return JsonSerializer.Deserialize<T>(this.ResponseContenString, myJsonSerializerOptions);
} /// <summary>
/// 得到带参数的Url
/// </summary>
/// <returns></returns>
private string GetUrlWithParameters()
{
if (this.ParameterDictionary == null)
{
return this.Url;
}
if (this.ParameterDictionary.Count == 0)
{
return this.Url;
} var myParameterList = new List<string>();
foreach (var myItem in this.ParameterDictionary)
{
myParameterList.Add(myItem.Key + "=" + myItem.Value);
}
return this.Url + "?" + string.Join("&", myParameterList);
} }
如果客户端是Js,就需要自己组织服务需要的数据了。代码入下所示。
var myFileReader = new FileReader();
var myFileName = ""; myFileReader.onloadend = function () {
var myFileResult = myFileReader.result;
var myFileLength = myFileResult.byteLength; var myFileEntity = new Object()
{
ServerPath: ""
};
Upload(); function Upload() { var myByteArray = myFileResult.slice(0, myFileLength);
var myBlob = new Blob([myByteArray]);
var myFile = new File([myBlob], myFileName);
var myFormData = new FormData();
myFormData.append("file", myFile)
myFormData.append("pEntity", json.stringify(myFileEntity));
request.post(myUrl, {
data: myFormData
}).then(function (data) {
myFileEntity = json.parse(data);
alert("上传文件结束。");
alert(json.stringify(myFileEntity));
}, function (err) {
alert(err);
return;
});
}
} myFileName = this.files[0].name;
myFileReader.readAsArrayBuffer(this.files[0]);
.Net Web API 005 Controller上传小文件的更多相关文章
- Wince 6.0适用 .NET 使用HttpRequest的Post上传文件,服务端的Web API接收Post上传上来的文件 代码
//调用的示例 private string fileName = "InStorageData.csv"; string filePath = parentPath + Comm ...
- SharePoint REST API - 使用REST API和jQuery上传一个文件
博客地址:http://blog.csdn.net/FoxDave 本篇主要通过两个代码示例来展示如何应用REST API和jQuery上传文件到SharePoint. 示例会使用REST接口和j ...
- Windows Azure 系列-- 使用Azure + Web API实现图片上传
1. 创建1个Azure账号,登录之后创建1个AzureStorage.左下方点Manage Access会看到Primary Access Key和Storage Account,记住它们的位置,等 ...
- web api 2.0 上传文件超过4M时,出现404错误
客户端代码 string path = "C:\\text.txt"; WebClient client = new WebClient(); Uri _address = new ...
- C# WEB.API 多图上传
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...
- windows上在linux客户端上传小文件lrzsz
yum install lrzsz 即可 rz上传,会打开本地图形化界面直接上传 基于centos系统,其他系统请找对应 的源码包编译 一下
- web项目使用fastdsf上传|下载文件
在上传代码中添加一下代码 suffix=suffix.substring(1); fast.FastDFSFile file = new fast.FastDFSFile(mFile.getBytes ...
- Azure VM上传小文件
因为需要传一些脚本到Azure的VM里,有个简单方法可以实现,如下 编辑这个rdp文件 点击确定,连接远程计算机 可以在我的电脑里看到本地硬盘
- webAPI文件上传时文件过大404错误的问题
背景:最近公司有个需求,外网希望自动保存数据到内网,内网有2台服务器可以相互访问,其中一台服务器外网可以访问,于是想在 这台服务器上放个中转的接口.后来做出来以后测试发现没有问题就放线上去了,不顾发现 ...
- Asp.net MVC利用WebUploader上传大文件出现404解决办法。
刚开始我上传小文件都是比较顺利的,但是上传了一个大文件大约有200M的压缩包就不行了.在chrome里面监视发现网络状态是404,我分析可能不是WebUploader的限制,应该是WebConfig限 ...
随机推荐
- iOS中的3种定时器
在iOS中有3种常见的定时器,它们会根据不同的场景进行选择使用. 1.DispatchSourceTimer: 基于GCD实现. 2.CADisplayLink:基于屏幕刷新实现. 3.Timer:基 ...
- drf重写authenticate方法实现多条件登录(源码分析)
drf重写authenticate方法实现多条件登录(源码分析) 1. 思路 JWT拓展的登录视图中, 在接受到用户名和密码时, 调用的也是Django的认证系统中提供的authenticate()来 ...
- 2020-08-23:描述HTTPS和HTTP的区别。
福哥答案2020-08-23: 1.地址区别http:http://开头.https:https://开头. 2.默认端口区别http:端口80.https:端口443. 3.数据传输区别http:明 ...
- 2022-03-01:k8s安装phpmyadmin,yaml如何写?
2022-03-01:k8s安装phpmyadmin,yaml如何写? 答案2022-03-01: yaml如下: apiVersion: apps/v1 kind: Deployment metad ...
- 2022-02-17:寻找最近的回文数。 给定一个表示整数的字符串 n ,返回与它最近的回文整数(不包括自身)。如果不止一个,返回较小的那个。 “最近的”定义为两个整数差的绝对值最小。 示例 1: 输
2022-02-17:寻找最近的回文数. 给定一个表示整数的字符串 n ,返回与它最近的回文整数(不包括自身).如果不止一个,返回较小的那个. "最近的"定义为两个整数差的绝对值最 ...
- phpstudy-sqlilabs-less-13
题目:POST - Double Injection - Single quotes- String - with twist 单引号与括号的双注入 先试试 uname=1' or 1=1#& ...
- 500行代码代码手写docker-将rootfs设置为只读镜像
(3)500行代码代码手写docker-将rootfs设置为只读镜像 本系列教程主要是为了弄清楚容器化的原理,纸上得来终觉浅,绝知此事要躬行,理论始终不及动手实践来的深刻,所以这个系列会用go语言实现 ...
- Intellij IDEA最新激活码,适合2022,2023和所有版本,永久更新
分享一下 IntelliJ IDEA 2023.1 最新激活注册码,破解教程如下,可免费永久激活,亲测有效,下面是详细文档哦~ 申明:本教程 IntelliJ IDEA 破解补丁.激活码均收集于网络, ...
- 上下文管理者(ServletContext)
作用1.获取全局初始化参数2.资源共享(servlet通信) 能让上下文呢的Servlet相互关联起来3.获取资源文件 生命周期创建服务器启动的时候会为每个项目创建一个servletContext上下 ...
- Oracle Users表空间重命名
需求:默认无法直接删除Oracle的users表空间,直接尝试删除会有报错如下: SQL> drop tablespace users including contents and datafi ...