# ImageDemo **Repository Path**: TheDragonLord/ImageDemo ## Basic Information - **Project Name**: ImageDemo - **Description**: .net core api 上传与加载图片 文件夹操作 swagger - **Primary Language**: C# - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-10-05 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ImageDemo .net core api 上传与加载图片 文件夹操作 swagger # 关于.net core API 图片上传与加载 文件夹 [TOC] #### 1.上传图片 ##### 1.配置Swagger 与文件夹、接口添加 1.建立.net core api 项目 下载 NuGet 包 Swashbuckle.AspNetCore 2.进入 starup 中 ConfigureServices 配置 ,添加如下代码 3.点击项目右键属性->生成->XML 文档文件 ✔ 上,接着在取消显示警告添加1591->保存 ```             services.AddSwaggerGen(s =>             {                 s.SwaggerDoc("v1", new Info                 {                     Title = "图片上传",                     Description = "图片上传测试",                     Version = "v1"                 });                 #region XML备注                 var basePath = Path.GetDirectoryName(AppContext.BaseDirectory);                 var imagePath = Path.Combine(basePath, "ImageDemo.xml");                 s.IncludeXmlComments(imagePath,true);                 #endregion             }); ``` 4.进入 starup 中 Configure 配置 ,添加如下代码 ``` app.UseSwagger(); app.UseSwaggerUI(s => s.SwaggerEndpoint("/swagger/v1/swagger.json", "v1版本")); ``` 5.点击 Properties 编辑为下面 ``` { /*"$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:59623", "sslPort": 44385 } },*/ "profiles": {/* "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "api/values", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } },*/ "ImageDemo": { "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } } ``` 6.运行项目,便可以看到结果,以上 Swagger 配置完毕 ##### 2.编写接口 1. 添加三个文件夹 * **Images** 存储图片 * 里面在设置一个名称为 **6** 的文件夹 * **IRepositories** 接口文件夹 * 新建接口类 **IImagesResource** * **Repositories** 实现类文件夹 * 新建实现类 **ImagesResource** 2. 实现类代码 ``` using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace ImageDemo.IRepositories { public interface IImagesResource { /// /// 加载图片 /// /// 路径 /// 图片名 /// FileContentResult LoadingPhoto(string path, string name); /// /// 上传图片 /// /// 图片 /// 路径 /// 图片名字 /// CustomStatusCode UpLoadPhoto(IFormFile formFile, string path); } } ``` #### 2.实现图片上传 _先上代码_ **实现类总代码** ``` using System; using System.IO; using System.Linq; using ImageDemo.IRepositories; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace ImageDemo.Repositories { public class ImagesResource:ControllerBase,IImagesResource { public static string[] LimitPictureType = {".PNG", ".JPG", ".JPEG", ".BMP", ".ICO"}; /// /// 加载图片 /// /// /// /// public FileContentResult LoadingPhoto(string path, string name) { path = Directory.GetCurrentDirectory() + path + name + ".jpeg"; FileInfo fi=new FileInfo(path); if (!fi.Exists) { return null; } FileStream fs = fi.OpenRead(); byte[] buffer=new byte[fi.Length]; //读取图片字节流 //从流中读取一个字节块,并在给定的缓冲区中写入数据。 fs.Read(buffer, 0, Convert.ToInt32(fi.Length)); var resource = File(buffer, "image/jpeg"); fs.Close(); return resource; } /// /// 上传图片 /// /// /// 路劲 /// public CustomStatusCode UpLoadPhoto(IFormFile formFile, string path) { CustomStatusCode code; var currentPictureWithoutExtension = Path.GetFileNameWithoutExtension(formFile.FileName); var currentPictureExtension = Path.GetExtension(formFile.FileName).ToUpper(); path = Directory.GetCurrentDirectory() + path; if (LimitPictureType.Contains(currentPictureExtension)) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string name = currentPictureWithoutExtension + ".jpeg"; path += name; using (var fs=System.IO.File.Create(path)) { formFile.CopyTo(fs); //Stream 都有 Flush() 方法, //根据官方文档的说法 //“使用此方法将所有信息从基础缓冲区移动到其目标或清除缓冲区,或者同时执行这两种操作” fs.Flush(); } code = new CustomStatusCode { Status = "200", Message = $"图片 {name} 上传成功" }; return code; } code = new CustomStatusCode { Status = "400", Message = $"图片上传失败,格式错误" }; return code; } } } ``` >**上面有个重点是实现类还继承了 ControllerBase,并且继承位置要在IImagesResource之前** 其中 **CustomStatusCode** 类是信息返回类下面贴下 ``` namespace ImageDemo { public class CustomStatusCode { public object Status; public object Message { get; set; } public object Data { get; set; } } } ``` _取出里面的上传图片代码_ ``` /// /// 上传图片 /// /// 图片 /// 路劲 /// public CustomStatusCode UpLoadPhoto(IFormFile formFile, string path) { CustomStatusCode code; var currentPictureWithoutExtension = Path.GetFileNameWithoutExtension(formFile.FileName); var currentPictureExtension = Path.GetExtension(formFile.FileName).ToUpper(); path = Directory.GetCurrentDirectory() + path; if (LimitPictureType.Contains(currentPictureExtension)) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string name = currentPictureWithoutExtension + ".jpeg"; path += name; using (var fs=System.IO.File.Create(path)) { formFile.CopyTo(fs); //Stream 都有 Flush() 方法, //根据官方文档的说法 //“使用此方法将所有信息从基础缓冲区移动到其目标或清除缓冲区,或者同时执行这两种操作” fs.Flush(); } code = new CustomStatusCode { Status = "200", Message = $"图片 {name} 上传成功" }; return code; } code = new CustomStatusCode { Status = "400", Message = $"图片上传失败,格式错误" }; return code; } ``` >解释阶段 1. IFormFile * 是上传的文件 2. var currentPictureWithoutExtension = Path.GetFileNameWithoutExtension(formFile.FileName); * 获取没有后缀扩展名的文件名,如传过来的是 **image.png**,经过上面 **currentPictureWithoutExtension** = **image** 3. var currentPictureExtension = Path.GetExtension(formFile.FileName).ToUpper(); * 得到 **formFile** 的扩展名并将其**大**写 4. path = Directory.GetCurrentDirectory() + path; * Directory.GetCurrentDirectory()得到当前程序的路劲,也就是和 **Starup.cs** 文件同等级的存在 5. string name = currentPictureWithoutExtension + ".jpeg"; * 这段代码是为了保存图片将后缀名统一,因为提取图片需要后缀名,以后提取图片方便点,_这是个很次的写法,当时没想到其他的方法_,这个方法不怎么可取后面我会改,先留个坑 6. fs.Flush(); * 这个解释是看网上的说明 * >Stream 都有 Flush() 方法,根据官方文档的说法“使用此方法将所有信息从基础缓冲区移动到其目标或清除缓冲区,或者同时执行这两种操作” 7. #### 3.加载图片 _贴代码_ ``` /// /// 加载图片 /// /// /// /// public FileContentResult LoadingPhoto(string path, string name) { path = Directory.GetCurrentDirectory() + path + name + ".jpeg"; FileInfo fi=new FileInfo(path); if (!fi.Exists) { return null; } FileStream fs = fi.OpenRead(); byte[] buffer=new byte[fi.Length]; //读取图片字节流 //从流中读取一个字节块,并在给定的缓冲区中写入数据。 fs.Read(buffer, 0, Convert.ToInt32(fi.Length)); var resource = File(buffer, "image/jpeg"); fs.Close(); return resource; } ``` 1. **File(buffer, "image/jpeg")** * 这个方法继承自 **ControllerBase** 并不是来自 using System.IO 中 * 至于怎样用 using System.IO; 把图片取出来...我还没学,望大佬教教 #### 4.Controller 控制器 _贴代码_ ``` ``` using ImageDemo.Db; using ImageDemo.IRepositories; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.IO; namespace ImageDemo.Controllers { [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { #region Inistial private readonly DbContext _dbContext; private readonly IImagesResource _imagesResource; private readonly ILogger _logger; public ValuesController( ILogger logger, DbContext dbContext, IImagesResource imagesResource) { _logger = logger; _dbContext = dbContext; _imagesResource = imagesResource; } #endregion /// /// 批量上传图片 /// /// /// [HttpPost] public IActionResult Post([FromForm] IFormFileCollection formCollection) { IList code=new List(); if (formCollection.Count > 0) foreach (IFormFile file in formCollection) { var currentCode=_imagesResource.UpLoadPhoto(file, @"\images\6\"); code.Add(currentCode); } return StatusCode(200,code); } /// /// 获取图片 /// /// /// [HttpGet] public IActionResult Get(string imgName) { var image = _imagesResource.LoadingPhoto("\\Images\\6\\", imgName); if (image == null) { _logger.LogInformation($"图片 {imgName} 不存在"); var code = new CustomStatusCode { Status = "404", Message = $"图片 {imgName} 加载不存在" }; return StatusCode(404, code); } return image; #region MyRegion /*string[] LimitPictureType = {".PNG", ".JPG", ".JPEG", ".BMP", ".GIF", ".ICO"}; GetFileName(di); string path = Directory.GetCurrentDirectory()+ $@"\Images\6\{imgName}"+".jpeg"; FileInfo fi = new FileInfo(path); FileStream fs = fi.OpenRead(); ; byte[] buffer = new byte[fi.Length]; //读取图片字节流 fs.Read(buffer, 0, Convert.ToInt32(fi.Length)); var response = File(buffer, "image/jpeg"); fs.Close(); return response; */ #endregion } private static IList path = new List(); //保存你图片名称 DirectoryInfo di = new DirectoryInfo(Directory.GetCurrentDirectory()+@"\Images\6\"); /// /// 加载目录内文件夹名 /// /// public static void GetFileName(DirectoryInfo info) { //获取该路径下的所有文件的列表 FileInfo[] fileInfo = info.GetFiles(); //开始得到图片名称 foreach (FileInfo subinfo in fileInfo) { //判断扩展名是否相同 // if (subinfo.Extension == extension) // { string strname = subinfo.Name; //获取文件名称 path.Add(strname); //把文件名称保存在泛型集合中 // } } } } } --- #### 5.想法,问题与 [GitHub](https://github.com/1045683477) >问题: >1. 上传图片可以多张上传,加载图片的方法本来也想多张加载,当时多张的话,图片就会变成字符串的形式,不知为何,求解 >2. 如果不用 **ControllerBse** 中的 **File** 那么该如何向页面传递图片 >有两个想法,朋友提的: >1. 那个加载图片直接建立一个html网页,将图片放进去,前端这样可以访问图片,应该可行,不知效率怎样 >2. 那个改后缀的实属下策,可以用建立数据库,两列,一列存储图片名,一列存储图片后缀,存储的时候可以将图片的名字改下,如果是用户头像,可以改为用户 **Id** 这样数字就唯一了