创建 Web API 来提供跨客户端和服务器的文件上传和下载是常有的事。本文将介绍如何通过 ASP.NET CORE 来实现。
首先在 Visual Studio 中创建空的 Web API 项目,然后选择目标框架 .Net Core 3.1。
创建名为 FileController 的控制器,提供操作文件的接口。
namespace FileAPI.Controllers
{
//[ApiController]
[Route("api/[controller]")]
public class FileController : ControllerBase
{
private readonly FileService _fileService;
public FileController(FileService fileService)
{
_fileService = fileService;
}
// download file(s) to client according path: rootDirectory/subDirectory with single zip file
[HttpGet("Download/{subDirectory}")]
public IActionResult DownloadFiles(string subDirectory)
{
try
{
var (fileType, archiveData, archiveName) = _fileService.FetechFiles(subDirectory);
return File(archiveData, fileType, archiveName);
}
catch (Exception exception)
{
return BadRequest($"Error: {exception.Message}");
}
}
// upload file(s) to server that palce under path: rootDirectory/subDirectory
[HttpPost("upload")]
public IActionResult UploadFile([FromForm(Name = "files")] List<IFormFile> files, string subDirectory)
{
try
{
_fileService.SaveFile(files, subDirectory);
return Ok(new { files.Count, Size = FileService.SizeConverter(files.Sum(f => f.Length)) });
}
catch (Exception exception)
{
return BadRequest($"Error: {exception.Message}");
}
}
}
}
创建服务层来实现文件传输的细节。
namespace FileAPI.Services
{
public class FileService
{
public void SaveFile(List<IFormFile> files, string subDirectory)
{
subDirectory = subDirectory ?? string.Empty;
var target = Path.Combine("D:\\webroot\\", subDirectory);
Directory.CreateDirectory(target);
files.ForEach(async file =>
{
if (file.Length <= 0) return;
var filePath = Path.Combine(target, file.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
});
}
public (string fileType, byte[] archiveData, string archiveName) FetechFiles(string subDirectory)
{
var zipName = $"archive-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";
var files = Directory.GetFiles(Path.Combine("D:\\webroot\\", subDirectory)).ToList();
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
files.ForEach(file =>
{
var theFile = archive.CreateEntry(file);
using (var streamWriter = new StreamWriter(theFile.Open()))
{
streamWriter.Write(File.ReadAllText(file));
}
});
}
return ("application/zip", memoryStream.ToArray(), zipName);
}
}
public static string SizeConverter(long bytes)
{
var fileSize = new decimal(bytes);
var kilobyte = new decimal(1024);
var megabyte = new decimal(1024 * 1024);
var gigabyte = new decimal(1024 * 1024 * 1024);
switch (fileSize)
{
case var _ when fileSize < kilobyte:
return $"Less then 1KB";
case var _ when fileSize < megabyte:
return $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB";
case var _ when fileSize < gigabyte:
return $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB";
case var _ when fileSize >= gigabyte:
return $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB";
default:
return "n/a";
}
}
}
}
现在一切都准备就绪,让我们启动我们的 Web API 应用程序并通过在Postman中填写一些请求来完成测试步骤。
测试下载接口,首先我们建立我们的根目录:“D:\webroot\” 和子目录:“report”,然后在里面放一些文件。
文件夹下的文件:D:\webroot\report\
在 Postman 下发起请求:
测试下载接口
1) 命名请求名称。
2) 使用GET方法填写相应的 URL。
3 ) 触发请求并检查响应。
测试上传接口,在Postman上发起请求:
1)命名请求名称。
2)使用POST方法填写相应的 URL 。
在 <Body> 标签上:选择表单数据
1、KEY:文件(类型选择文件),VALUE:选择您想要的任何文件。
2、KEY:子目录,VALUE:目标文件夹。 ✨您可以根据需要上传单个文件或多个文件。 ✨KEY 的属性名称映射到 WEB API 参数的名称。
3)发出请求并检查响应。
如果您想将您的 Web API 从 .Net Core 2.2 移植到 3.1,您需要注意一些事情
如果您的客户端的数据表单(网页)没有给出特定名称,则以下示例在 Web API .Net Core 2.2 下运行。
例如:
<form method=”post” enctype=”multipart/form-data” action=”/api/upload”>
<input type=”file” name=”” multiple />
<br />
<input type=”submit” value=”submit” />
</form>
[HttpPost(“upload”)]public async Task<IActionResult> UploadFile([FromForm]List<IFormFile> files){…}
但是对于 Net Core 3.1,您将无法从请求中绑定模型 IFormFile(这意味着列表:files.Count 始终返回零):
绑定失败
正确的方法是:
[HttpPost("upload")]public IActionResult UploadFile([FromForm(Name = ""] List<IFormFile> files, string subDirectory){...}
参考链接:File uploads in ASP.NET Core
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。