在 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.mzph.cn/web/65398.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue2迁移至rsbuild

背景 由于远程机器配置较低&#xff0c;每次运行vue2项目都会非常卡。后期项目文件、路由更多的时候&#xff0c;启动到一半直接会跳出open too many files类似的错误&#xff0c;尝试将路由屏蔽掉只剩下开发所需的一个路由也不行&#xff08;不是说webpack的打包是全部打包&am…

智能手机租赁系统全新模式改变消费习惯与商家盈利路径

内容概要 智能手机租赁系统的崛起&#xff0c;让我们瞄到了一个消费市场的新风向标。想象一下&#xff0c;传统上人们总是为了最新款手机奋不顾身地排队、借钱甚至是透支信用卡。现在&#xff0c;通过灵活的租赁选项&#xff0c;消费者可以更加随意地体验高科技产品&#xff0…

[项目实战2]贪吃蛇游戏

目录 贪吃蛇游戏&#xff1a;&#xff1a; 一、游戏效果及功能实现&#xff1a; 1.规则 ​​​​​​​ ​​​​​​​ ​​​​​​​ 2.基本功能实现 ​​​​​​​ ​​​​​​​ ​​​​​​​ 3.技术要点 ​​​​​​​…

浏览器报错:您的连接不是私密连接,Kubernetes Dashboard无法打开

问题描述 部署完成Kubernetes Dashboard后&#xff0c;打开HTTPS的web页面&#xff0c;Chrome和Edge浏览器都无法正常加载页面&#xff0c;会提示您的连接不是私密连接的报错。 ​​​​​​​​​​​​ 原因&#xff1a; 浏览器不信任这些自签名的ssl证书&#xff0c;为了…

关于量子神经网络的思考

其实在写这篇文章之前想了很多&#xff0c;主要是想法太超前&#xff0c;有可能颠覆未来机器智能行业甚至是影响世界。 1、计算机的历史 计算机的历史可以追溯到20世纪中叶&#xff0c;最早的电子计算机如ENIAC和EDVAC采用了冯诺依曼架构&#xff08;John von Neumann Archit…

docker pull(拉取镜像)的时候,无法下载或者卡在Waiting的解决方法

docker pull的时候&#xff0c;卡在Waiting的解决方法 一般情况&#xff08;大部分镜像都可以拉取&#xff09;更换镜像源 进一步&#xff08;如es等拉取不到&#xff09;在镜像同步站搜索详细步骤 还可以在挂载的时候&#xff0c;让其下载对应的版本 一般情况&#xff08;大部…

PHP二维数组去除重复值

Date: 2025.01.07 20:45:01 author: lijianzhan PHP二维数组内根据ID或者名称去除重复值 代码示例如下&#xff1a; // 假设 data数组如下 $data [[id > 1, name > Type A],[id > 2, name > Type B],[id > 1, name > Type A] // 重复项 ];// 去重方法 $dat…

注册中心如何选型?Eureka、Zookeeper、Nacos怎么选

这是小卷对分布式系统架构学习的第9篇文章&#xff0c;第8篇时只回答了注册中心的工作原理的内容&#xff0c;面试官的第二个问题还没回答&#xff0c;今天再来讲讲各个注册中心的原理&#xff0c;以及区别&#xff0c;最后如何进行选型 上一篇文章&#xff1a;如何设计一个注册…

SQL使用视图

本文将介绍什么是视图&#xff0c;它们怎样工作&#xff0c;何时使用它们。 1. 视图 视图是虚拟的表。与包含数据的表不一样&#xff0c;视图只包含使用时动态检索数据的查询。 说明&#xff1a;SQLite 的视图 SQLite 仅支持只读视图&#xff0c;所以视图可以创建&#xff…

Three.js - 打开Web 3D世界的大门

文章目录 前言一、Three.js 的起源与背景二、Three.js 的特点三、Three.js 的核心组件详解四、实际应用案例结语 前言 Three.js 是一个基于JavaScript的库&#xff0c;它极大地简化了使用WebGL创建3D图形的过程。通过封装复杂的WebGL API&#xff0c;Three.js为开发者提供了一…

恒压恒流原边反馈控制芯片 CRE6289F

CRE6289F 系列产品是一款内置高压 MOS 功率开关管的高性能多模式原边控制的开关电源芯片。较少的外围元器件、较低的系统成本设计出高性能的交直流转换开关电源。CRE6289F 系列产品提供了极为全面和性能优异的智能化保护功能&#xff0c;包括逐周期过流保护、软启动、芯片过温保…

开源 AI 智能名片 2+1 链动模式商城小程序在商业营销中的心理博弈与策略应用

摘要&#xff1a;在当今竞争激烈的商业环境中&#xff0c;理解消费者心理对营销成败起着关键作用。本文聚焦于消费者 “占便宜” 心理&#xff0c;深入探讨开源 AI 智能名片 21 链动模式商城小程序如何利用这一心理&#xff0c;在 “双十一”“双十二” 等购物热潮背景下&#…

01 数据分析介绍及工具准备

数据分析介绍及工具准备 一、工具准备二、下载和使用Anaconda三、jupyter notebook常用快捷键 一、工具准备 数据科学库 NumPy&#xff0c;SciPy&#xff0c;Pandas&#xff0c;Scikit-Learn 数据可视化库 Matplotlib&#xff0c;Seaborn 编译器 Jupyter Notebook 数据科…

opencv摄像头标定程序实现

摄像头标定是计算机视觉中的一个重要步骤&#xff0c;用于确定摄像头的内参&#xff08;如焦距、主点、畸变系数等&#xff09;和外参&#xff08;如旋转矩阵和平移向量&#xff09;。OpenCV 提供了方便的工具来进行摄像头标定。下面分别给出 C 和 Python 的实现。 1. C 实现…

后端Java开发:第十三天

第十三天&#xff1a;继承 - 面向对象的核心概念 欢迎来到第十三天的学习&#xff01;今天&#xff0c;我们将深入探讨 Java 中的 继承&#xff08;Inheritance&#xff09;&#xff0c;这是面向对象编程的四大基本特性之一。继承是指一个类&#xff08;子类&#xff09;通过继…

java项目之网上租贸系统源码(springboot+mysql+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的网上租贸系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于Spring Boot的网上租贸…

协方差矩阵

协方差矩阵是一个对称矩阵&#xff0c;用来描述多个随机变量之间的协方差关系。协方差反映了两个随机变量如何共同变化的趋势&#xff0c;协方差矩阵将这种关系扩展到了多维数据。 1. 定义 假设有一个 n 维随机向量 &#xff0c;协方差矩阵 Σ 定义为&#xff1a; 其中&#…

spring boot controller放到那一层

在 Spring Boot 应用程序中&#xff0c;Controller 层通常被放置在应用程序的 表示层&#xff08;Presentation Layer&#xff09; 或 用户界面层&#xff08;UI Layer&#xff09; 中。Controller 层的主要职责是处理用户的 HTTP 请求&#xff0c;并将请求转发给服务层进行业务…

计算机网络之---局域网

什么叫局域网 局域网&#xff08;LAN&#xff0c;Local Area Network&#xff09; 是指在一个相对较小的区域内&#xff0c;如家庭、办公室、学校、企业等&#xff0c;连接多个计算机和设备的网络。局域网的特点是覆盖范围小、传输速度快、构建成本较低。 局域网的主要特点&…

Spring Boot + Jasypt 实现application.yml 属性加密的快速示例

Jasypt(Java Simplified Encryption)是一个专为Java应用程序设计的开源加密库,旨在简化加密和解密流程,保护敏感数据如密码、API密钥等。 jasypt-spring-boot-starter允许开发者在Spring Boot应用中轻松地实现加密和解密功能。 本篇介绍使用 jasypt-spring-boot-starter 以…