關於.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.編寫接口
-
添加三個文件夾
- Images 存儲圖片
- 里面在設置一個名稱為 6 的文件夾
- IRepositories 接口文件夾
- 新建接口類 IImagesResource
- Repositories 實現類文件夾
- 新建實現類 ImagesResource
- Images 存儲圖片
-
實現類代碼
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace ImageDemo.IRepositories
{
public interface IImagesResource
{
/// <summary>
/// 加載圖片
/// </summary>
/// <param name="path">路徑</param>
/// <param name="name">圖片名</param>
/// <returns></returns>
FileContentResult LoadingPhoto(string path, string name);
/// <summary>
/// 上傳圖片
/// </summary>
/// <param name="formFile">圖片</param>
/// <param name="path">路徑</param>
/// <param name="name">圖片名字</param>
/// <returns></returns>
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"};
/// <summary>
/// 加載圖片
/// </summary>
/// <param name="path"></param>
/// <param name="name"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 上傳圖片
/// </summary>
/// <param name="formFile"></param>
/// <param name="path">路勁</param>
/// <returns></returns>
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; }
}
}
取出里面的上傳圖片代碼
/// <summary>
/// 上傳圖片
/// </summary>
/// <param name="formFile">圖片</param>
/// <param name="path">路勁</param>
/// <returns></returns>
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;
}
解釋階段
- IFormFile
- 是上傳的文件
- var currentPictureWithoutExtension = Path.GetFileNameWithoutExtension(formFile.FileName);
- 獲取沒有后綴擴展名的文件名,如傳過來的是 image.png,經過上面 currentPictureWithoutExtension = image
- var currentPictureExtension = Path.GetExtension(formFile.FileName).ToUpper();
- 得到 formFile 的擴展名並將其大寫
- path = Directory.GetCurrentDirectory() + path;
- Directory.GetCurrentDirectory()得到當前程序的路勁,也就是和 Starup.cs 文件同等級的存在
- string name = currentPictureWithoutExtension + “.jpeg”;
- 這段代碼是為了保存圖片將后綴名統一,因為提取圖片需要后綴名,以后提取圖片方便點,這是個很次的寫法,當時沒想到其他的方法,這個方法不怎么可取后面我會改,先留個坑
- fs.Flush();
- 這個解釋是看網上的說明
-
Stream 都有 Flush() 方法,根據官方文檔的說法“使用此方法將所有信息從基礎緩沖區移動到其目標或清除緩沖區,或者同時執行這兩種操作”
3.加載圖片
貼代碼
/// <summary>
/// 加載圖片
/// </summary>
/// <param name="path"></param>
/// <param name="name"></param>
/// <returns></returns>
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;
}
- File(buffer, “image/jpeg”)
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<ValuesController> _logger;
public ValuesController(
ILogger<ValuesController> logger,
DbContext dbContext,
IImagesResource imagesResource)
{
_logger = logger;
_dbContext = dbContext;
_imagesResource = imagesResource;
}
#endregion
/// <summary>
/// 批量上傳圖片
/// </summary>
/// <param name="file"></param>
/// <param name="formCollection"></param>
[HttpPost]
public IActionResult Post([FromForm] IFormFileCollection formCollection)
{
IList<CustomStatusCode> code=new List<CustomStatusCode>();
if (formCollection.Count > 0)
foreach (IFormFile file in formCollection)
{
var currentCode=_imagesResource.UpLoadPhoto(file, @"\images\6\");
code.Add(currentCode);
}
return StatusCode(200,code);
}
/// <summary>
/// 獲取圖片
/// </summary>
/// <param name="imgName"></param>
/// <returns></returns>
[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<string> path = new List<string>(); //保存你圖片名稱
DirectoryInfo di = new DirectoryInfo(Directory.GetCurrentDirectory()+@"\Images\6\");
/// <summary>
/// 加載目錄內文件夾名
/// </summary>
/// <param name="info"></param>
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
問題:
- 上傳圖片可以多張上傳,加載圖片的方法本來也想多張加載,當時多張的話,圖片就會變成字符串的形式,不知為何,求解
- 如果不用 ControllerBse 中的 File 那么該如何向頁面傳遞圖片
有兩個想法,朋友提的:
- 那個加載圖片直接建立一個html網頁,將圖片放進去,前端這樣可以訪問圖片,應該可行,不知效率怎樣
- 那個改后綴的實屬下策,可以用建立數據庫,兩列,一列存儲圖片名,一列存儲圖片后綴,存儲的時候可以將圖片的名字改下,如果是用戶頭像,可以改為用戶 Id 這樣數字就唯一了