当前位置: 首页 > article >正文

在 ASP.NET CORE 中上传、下载文件

创建 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

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。 


http://www.kler.cn/a/470790.html

相关文章:

  • 利用大语言模型解决推理任务
  • c++领域展开第十幕——类和对象(内存管理——c/c++内存分布、c++内存管理方式、new/delete与malloc/free区别)超详细!!!!
  • huggingface 下载方法 测试ok
  • 【Qt】控件概述和QWidget核心属性1(enabled、geometry、windowTitle、windowIcon、QRC机制)
  • 将本地的 Git 仓库上传到 GitHub 上(github没有该仓库)
  • 3.final关键字
  • train_args = TrainingArguments()里面的全部参数使用
  • 中电金信携手华为发布“全链路实时营销解决方案”,重塑金融营销数智新生态
  • 设计模式-结构型-适配器模式
  • flutter 专题二十四 Flutter性能优化在携程酒店的实践
  • 计算机毕业设计Python+Vue.js游戏推荐系统 Steam游戏推荐系统 Django Flask 游 戏可视化 游戏数据分析 游戏大数据 爬虫
  • AI巡检系统在安全生产管理中的创新应用
  • 游戏引擎学习第74天
  • Redis 数据库源码分析
  • Opencv实现Sobel算子、Scharr算子、Laplacian算子、Canny检测图像边缘
  • stm32 移植RTL8201F(正点原子例程为例)
  • Easyexcel-4.0.3读取文件内容时遇到“java.lang.ClassNotFoundException”
  • 《从入门到精通:蓝桥杯编程大赛知识点全攻略》(二)-递归实现组合型枚举、带分数问题
  • libaom 源码分析线程结构
  • uni-app 页面生命周期及组件生命周期汇总(Vue2、Vue3)
  • 特征点检测与匹配——MATLAB R2022b
  • 2025资源从哪里来!
  • vue3-dom-diff算法
  • Postman接口测试02|接口用例设计
  • 云原生周刊:K8s 生态系统的五大趋势预测
  • IDEA中Lombok不能使用,找不到get方法