1. 程式人生 > >.NET Core API框架實戰(三) 使用Swagger文件實現上傳檔案

.NET Core API框架實戰(三) 使用Swagger文件實現上傳檔案

  1. 介紹

  2. 在Swagger中利用 IOperationFilter 操作來實現檔案上傳

  3. 檔案上傳

1、介紹 

寫過介面的朋友都知道,除錯、維護介面是一件非常重要的一件事;swagger是一款非常不錯的介面文件工具,那麼在本期中,我們就用swagger介面文件來實現檔案上傳功能;話不多說,直接進入主題;

2、 在Swagger中利用 IOperationFilter 操作來實現檔案上傳

首先建立一個類,取名 SwaggerFileHeaderParameter,並繼承為IOperationFilter

public class SwaggerFileHeaderParameter: IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            operation.Parameters = operation.Parameters ?? new List<IParameter>();

            if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
                !context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var fileParameters = context.ApiDescription.ActionDescriptor.Parameters.Where(n => n.ParameterType == typeof(IFormFile)).ToList();

            if (fileParameters.Count < 0)
            {
                return;
            }

            foreach (var fileParameter in fileParameters)
            {
                if (fileParameter.BindingInfo == null)
                {
                    operation.Parameters.Add(new NonBodyParameter
                    {
                        Name = fileParameter.Name,
                        In = "formData",
                        Description = "檔案上傳",
                        Required = true,
                        Type = "file"
                    });
                    operation.Consumes.Add("multipart/form-data");
                }
                else
                {
                    var parameter = operation.Parameters.Single(n => n.Name == fileParameter.Name);
                    operation.Parameters.Remove(parameter);
                    operation.Parameters.Add(new NonBodyParameter
                    {
                        Name = parameter.Name,
                        In = "formData",
                        Description = parameter.Description,
                        Required = parameter.Required,
                        Type = "file"
                    });
                    operation.Consumes.Add("multipart/form-data");
                }

            }  
        }
    }

第二步,在Startup中註冊SwaggerFileHeaderParameter

  c.OperationFilter<SwaggerFileHeaderParameter>();

檔案上傳標籤已註冊完畢;

3、檔案上傳

注意:

.Net Core 是通過該類 IFormFile 進行檔案上傳,WebApi預設整合ControllerBase,但IFormFile必須基於Controller;

好,那我們直接上程式碼吧。

 /// <summary>
    /// 檔案上傳
    /// </summary>
    [Route("[controller]/[action]")]
    public class HomeController : Controller
    {
        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly SystemConfig config;
        /// <summary>
        /// 構造
        /// </summary>
        /// <param name="hostingEnvironment"></param>
        /// <param name="options"></param>
        public HomeController(
            IHostingEnvironment hostingEnvironment,
            IOptions<SystemConfig> options
            )
        {
            _hostingEnvironment = hostingEnvironment;//依賴注入類,因為.net core 已經沒有Server.MapPath()屬性了
            config = options.Value;
        }
        /// <summary>
        /// 上傳圖片
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActionResult> UploadImg(UploadInput input)
        {
            try
            {
                var date = Request;
                var files = Request.Form.Files;
                if (files.Count == 0)
                    return Ok($"圖片未上傳,請上傳檔案");
                long size = files.Sum(f => f.Length);//獲取檔案大小
                if (size > config.FileFormat.Img.B)
                    return Ok($"圖片過大,圖片大小為{config.FileFormat.Img.Size}M");
                string webRootPath = _hostingEnvironment.WebRootPath;
                string contentRootPath = _hostingEnvironment.ContentRootPath;//獲取伺服器路徑
                //儲存檔名路徑
                foreach (var formFile in files)
                {
                    if (formFile.Length > 0)
                    {
                        string fileExt = formFile.FileName.Substring(formFile.FileName.LastIndexOf('.'), formFile.FileName.Length - formFile.FileName.LastIndexOf('.'));//獲取字尾名
                        if (!config.FileFormat.Img.Exts().Contains(fileExt.ToLower()))
                            return Ok($"圖片格式不正確,圖片為格式為{config.FileFormat.Img.ExtStr}");
                        long fileSize = formFile.Length; //獲得檔案大小,以位元組為單位
                        var newFileName = Guid.NewGuid().ToString() + fileExt; //隨機生成新的檔名
                        string path = $"{webRootPath}/Content/Upload/{input.FolderName}";//資料夾路徑
                        if (!PathHelper.IsExist(path))//查詢目錄是否存在
                            PathHelper.CreateFiles(path);//建立目錄
                        var filePath = $"{path}/{ newFileName}";//檔案路徑
                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            await formFile.CopyToAsync(stream);
                            //備份檔案
                            PathHelper.Backup(filePath, $"{config.FileFormat.BackupUrl}/{input.FolderName}", newFileName);
                        }
                    }
                }
                return Ok("上傳成功");
            }
            catch (Exception ex)
            {
                return Ok(ex.Message);
            }
        }
    }

附加:備份檔案


    public static class PathHelper
    {
        /// <summary>
        /// 是否是絕對路徑
        /// windows下判斷 路徑是否包含 ":"
        /// Mac OS、Linux下判斷 路徑是否包含 "\"
        /// </summary>
        /// <param name="path">路徑</param>
        /// <returns></returns>
        public static bool IsAbsolute(string path)
        {
            return Path.VolumeSeparatorChar == ':' ? path.IndexOf(Path.VolumeSeparatorChar) > 0 : path.IndexOf('\\') > 0;
        }
        /// <summary>
        /// 路徑是否存在
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsExist(string path)
        {
            return Directory.Exists(path);
        }
        /// <summary>
        /// 建立目錄
        /// </summary>
        /// <param name="path"></param>
        public static void CreateFiles(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }
        /// <summary>
        /// 備份檔案
        /// </summary>
        /// <param name="sourcefile">檔案路徑</param>
        /// <param name="targetfile">備份檔案路徑</param>
        /// <param name="filename">檔名</param>
        public static void Backup(string sourcefile, string targetfile, string filename)
        {
            if (!Directory.Exists(targetfile))
            {
                Directory.CreateDirectory(targetfile);
            }
            File.Copy(sourcefile, $"{targetfile}/{filename}", true);
        }
    }

好,講到這裡本期也告一段落了,現在我們一起來實現一下上傳檔案吧!

執行專案

可以看到我們剛剛建立的上傳檔案標籤;

可以看到我們上傳的檔案。