.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桌面软件,入下图所示。

.Net Web API 005 Controller上传小文件

调用代码入下所示。

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

发表评论

评论已关闭。

相关文章