NET8环境WebAPI实现文件的压缩及下载
目录
- 1、文件下载的原理
- 2、具体实现
- 2.1 提前准备
- 2.2 服务器端的实现
- 2.3 请求端的实现
- 3、代码下载
- 4、更多特性
- 4.1 单独压缩文件
- 4.2 解析
- 4.2.1 整体解析
- 4.2.2 单个文件解析
- 4.3 其他
- 4.3.1 设置压缩级别
- 4.3.2 密码保护
- 4.3.3 进度反馈
- 5、参考资料
1、文件下载的原理
在实际应用环境中,文件的下载是一个特别常见的需求。为了传输文件的大小,往往需要对文件进行压缩,因此就涉及到文件的压缩及文件的下载,具体步骤有5步。(1)、请求端发出文件的请求。这个可以根据实际需求,使用get/post及参数,发起一个请求。(2)、服务器收到请求后,会根据需求生成(或者准备)相关文件(最常用的例子就是:患者通过医院App下载处方、门诊记录单、诊断证明书之类)【这一步往往是偏向业务相关】。(3)然后将这些生成的文件,压缩成zip文件格式。(4)、服务端返回数据。(5)、客户端收到数据后,解析Response
中的Stream
,并使用FileStream
将文件存储到本地。
具体的原理如下图所示
2、具体实现
2.1 提前准备
我们提前准备了文件(这步主要是模拟实际业务中生成的文件夹及文件)。在fhirs文件夹下有一个index.xml
文件和emrfhirs
文件夹,并且在emrfhirs
文件夹内有001fhir.json
、002fhir.json
、003fhir.json
三个文件。文档的目录结构如下:
2.2 服务器端的实现
创建webapi
项目,实现下载文件的方法。具体代码如下
[HttpPost]
public async Task<ActionResult> getCompressionFile()
{try{/** 接收客户端的参数,本示例为了简化,不进行处理IFormCollection form = HttpContext.Request.Form;string? username = form["UserName"];string? password = form["Password"];string? remoteFilePath = form["RemotePath"];**/string source_folder = @"D:\data\fhirs"; //需要压缩的文件的路径,就是刚才上面提到的文件夹及文件string destination_path = @"D:\data\fhirsemr.zip"; //要将上面的文件夹变成的压缩文件// using System.IO.Compression;//将文件进行压缩await Task.Run(() =>{ZipFile.CreateFromDirectory(source_folder, destination_path);});//这个地方涉及一个知识//zip压缩文件,它的content-type是application/x-zip-compressed//rar压缩文件,它的content-type是application/octet-streamvar stream = new FileStream(destination_path, FileMode.Open, FileAccess.Read);return new FileStreamResult(stream, "application/x-zip-compressed"){FileDownloadName = "ermfile"};}catch (Exception ex){throw new Exception(ex.Message);}
}
上面就是服务端的代码
2.3 请求端的实现
客户端的请求端实现如下
//url:服务端的地址
//localFileFullPath:将文件存储到本地的路径
//otherParams:给业务使用的参数
private string GetFile(string url, string localFileFullPath, string otherParams)
{try{Uri uri = new Uri(url);HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);request.Method = "post"; //post、getrequest.ContentType = "application/x-www-form-urlencoded;charset=utf-8";request.KeepAlive = true;request.Credentials = CredentialCache.DefaultCredentials;using (Stream requestStream = request.GetRequestStream()){byte[] formDataBytes = Encoding.UTF8.GetBytes(otherParams);requestStream.Write(formDataBytes, 0, formDataBytes.Length);}HttpWebResponse response = (HttpWebResponse)request.GetResponse();//判断路径,并创建路径string path = Path.GetDirectoryName(localFileFullPath);if (!Directory.Exists(path) && !string.IsNullOrEmpty(path)){Directory.CreateDirectory(path);}//将文件using (FileStream fs = new FileStream(localFileFullPath, FileMode.Create, FileAccess.Write, FileShare.None)){using (Stream responseStream = response.GetResponseStream()){//创建本地文件写入流byte[] bArr = new byte[1024];int iTotalSize = 0;int size = responseStream.Read(bArr, 0, bArr.Length);while (size > 0){iTotalSize += size;fs.Write(bArr, 0, size);size = responseStream.Read(bArr, 0, bArr.Length);}}}return "Success-获取文件成功";}catch (Exception ex){return "Error-"+ex.Message;}
}
3、代码下载
代码比较简单,无代码
4、更多特性
4.1 单独压缩文件
如果你只想压缩特定的文件,而不是整个文件夹,你可以使用FileStream和ZipArchive来实现。实际上就是NET
中的文件操作
using System.IO;
using System.IO.Compression;string startPath = @"c:\example\file.txt"; // 要压缩的文件路径
string zipPath = @"c:\example\result.zip"; // 压缩后的ZIP文件路径using (FileStream zipToOpen = new FileStream(zipPath, FileMode.Create))
{using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create)){ZipArchiveEntry readmeEntry = archive.CreateEntry("file.txt");using (StreamWriter writer = new StreamWriter(readmeEntry.Open())){using (StreamReader reader = new StreamReader(startPath)){string content = reader.ReadToEnd();writer.Write(content);}}}
}
4.2 解析
4.2.1 整体解析
解压文件同样简单。我们可以使用ZipFile类的ExtractToDirectory方法来解压ZIP文件到指定文件夹:
using System.IO.Compression;string zipPath = @"c:\example\start.zip"; // 要解压的ZIP文件路径
string extractPath = @"c:\example\extract"; // 解压后的文件夹路径ZipFile.ExtractToDirectory(zipPath, extractPath);
这段代码会将start.zip文件解压到extract文件夹中。
4.2.2 单个文件解析
如果你需要更细粒度的控制,比如只解压ZIP文件中的特定文件,你可以使用ZipArchive来实现:
using System.IO;
using System.IO.Compression;string zipPath = @"c:\example\start.zip"; // 要解压的ZIP文件路径
string extractPath = @"c:\example\extract"; // 解压后的文件夹路径
string fileToExtract = "file.txt"; // 要解压的文件名using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{ZipArchiveEntry entry = archive.GetEntry(fileToExtract);if (entry != null){string fullPath = Path.Combine(extractPath, entry.FullName);entry.ExtractToFile(fullPath, overwrite: true);}
}
这段代码会从start.zip文件中解压出file.txt文件到extract文件夹中
4.3 其他
4.3.1 设置压缩级别
在压缩文件时,你可以指定压缩级别来优化压缩效果。ZipArchiveMode.Create
方法接受一个CompressionLevel
枚举参数,允许你选择不同的压缩级别:
using (FileStream zipToOpen = new FileStream(zipPath, FileMode.Create))
{using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create, true)){// ... 添加文件到ZIP归档中}
}
在这个例子中,第三个参数是布尔值,表示是否压缩归档中的条目。你也可以通过ZipArchiveEntry.CompressionLevel属性为单个条目设置压缩级别。
4.3.2 密码保护
.NET
的System.IO.Compression
命名空间不支持为ZIP文件添加密码保护。如果你需要这个功能,你可能需要使用第三方库,如DotNetZip
4.3.3 进度反馈
在压缩或解压大文件时,提供进度反馈是一个很好的用户体验。然而,System.IO.Compression
命名空间并没有直接提供进度反馈的机制。你可以通过计算处理的文件大小与总大小来估算进度,并使用例如IProgress<T>
接口来报告进度。
5、参考资料
这篇文章主要参考了这篇文章:NET环境下使用原生方法实现文件压缩与解压
相关文章:

NET8环境WebAPI实现文件的压缩及下载
目录 1、文件下载的原理2、具体实现2.1 提前准备2.2 服务器端的实现2.3 请求端的实现 3、代码下载4、更多特性4.1 单独压缩文件4.2 解析4.2.1 整体解析4.2.2 单个文件解析 4.3 其他4.3.1 设置压缩级别4.3.2 密码保护4.3.3 进度反馈 5、参考资料 1、文件下载的原理 在实际应用环…...
Ubuntu 18 使用NVIDIA上的HDMI输出声音
前言 在未做修改之前,Settings -> Sound -> Output 里面只有 Digital Output(S/PDIF) - Built-in Audio 不显示HDMI的输出设备检查当前存在的音频设备 sudo lspci -v | grep -A7 -i "audio"输出: 从输出可以看出来是有两个设备的 00:1…...

C#模拟量线性变换小程序
1、一步步建立一个C#项目 一步步建立一个C#项目(连续读取S7-1200PLC数据)_s7协议批量读取-CSDN博客文章浏览阅读1.7k次,点赞2次,收藏4次。本文详细介绍了如何使用C#构建一个项目,通过S7net库连接并连续读取S7-1200 PLC的数据,包括创建窗体应用、配置存储位置、安装S7net库…...

跟《经济学人》学英文:2024年08月10日这期 How AI models are getting smarter
How AI models are getting smarter Deep neural networks are learning diffusion and other tricks 原文: Type in a question to ChatGPT and an answer will materialise. Put a prompt into DALL-E 3 and an image will emerge. Click on TikTok’s “for y…...

Spring Web MVC入门(上)
1. Spring Web MVC Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为“spring MVC”; 什么是Servlet呢? Servlet…...
【c++】公差判断函数 isInTolerance
定义: isInTolerance 函数用来判断一个特定数值(变量)是否在以某个中心值为基准 ,给定半径的范围内。这个函数包含了一个可选的参数 includeEndpoints(默认为 true), 用于决定范围是否包含其端点…...

电脑新加的硬盘如何分区?新加硬盘分区选MBR还是GPT
最近有网友问我,电脑新加的硬盘如何分区?电脑新加的硬盘分区选MBR还是GPT要看引导模式采用uefi还是传统的legacy模式,如果采用的是uefi引导模式,分区类型对应的就是gpt分区(guid),如果引导模式采用的是legacy,对应的分区类型为mb…...
白骑士的Matlab教学基础篇 1.3 控制流
系列目录 上一篇:白骑士的Matlab教学基础篇 1.2 MATLAB基础语法 控制流是编程中的核心概念,通过控制程序执行的顺序,从而实现复杂的逻辑操作。MATLAB 提供了多种控制流语句,包括条件语句、循环语句以及循环控制语句。掌握这些控制…...
设计模式 - 适配器模式
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 引言一、适配器…...
docker部署minIO
docker部署minIO 旧版本新版本 旧版本 #-u 以root用户运行容器;--privilegedtrue 给予容器命令访问权限 docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z docker run -p 9001:9000 --name minio -d \-u root --privilegedtrue \-e "MINIO_ROOT_USERmin…...

「Pytorch」BF16 Mixed Precision Training
在深度学习领域,神经网络的训练性能瓶颈常常出现在 GPU显存的使用上。主要表现为两方面: 单卡上可容纳的模型和数据量有限;显存与计算单元之间的带宽和延迟限制了运算速度; 为了解决显卡瓶颈的问题,涌现了不同的解决…...

论文阅读:Efficient Core Maintenance in Large Bipartite Graphs | SIGMOD 2024
还记得我们昨天讨论的《Querying Historical Cohesive Subgraphs over Temporal Bipartite Graphs》这篇论文吗? https://blog.csdn.net/m0_62361730/article/details/141003301 这篇(还没看的快去看) 这篇论文主要研究如何在时间双向图上查询历史凝聚子图,而《E…...

LLMOps — 使用 BentoML 为 Llama-3 模型提供服务
使用 BentoML 和 Runpod 快速设置 LLM API 经常看到数据科学家对 LLM 的开发感兴趣,包括模型架构、训练技术或数据收集。然而,我注意到,很多时候,除了理论方面,许多人在以用户实际使用的方式提供这些模型时遇到了问题…...

微软蓝屏事件揭秘:有问题的数据引发内存读取越界
讲动人的故事,写懂人的代码 CrowdStrike前一阵在官网上发布了上周爆发的全球企业微软蓝屏事件的官方初步复盘结果。其中谈到了这次事件的根本原因: 2024年7月19日,我们部署了两个额外的IPC模板实例。由于内容验证器中的一个bug,使…...

NASA:北极ARCTAS差分吸收激光雷达(DIAL)遥感数据
ARCTAS Differential Absorption Lidar (DIAL) Remotely Sensed Data ARCTAS差分吸收激光雷达(DIAL)遥感数据 简介 ARCTAS差分吸收激光雷达(DIAL)遥感数据是一种远程感测技术,用于测量大气中不同波长的激光辐射被大…...

Android 文件上传与下载
在实际开发涉及文件上传不会自己写上传代码,一般 会集成第三网络库来做图片上传,比如android-async-http,okhttp等,另外还有七牛也提供 了下载和上传的API。 1.项目用到的图片上传的关键方法: 这里用到一个第三方的库…...

Java语言的充电桩系统Charging station system
介绍 SpringBoot 框架,充电桩平台充电桩系统充电平台充电桩互联互通协议云快充协议1.5-1.6协议新能源汽车二轮车公交车二轮车充电-四轮车充电充电源代码充电平台源码Java源码-共享充电桩-充电桩软件 软件介绍 小程序端:城市切换、附近电站、电桩详情页…...

RCE之无参数读取文件
什么是无参数? 顾名思义,就是只使用函数,且函数不能带有参数,这里有种种限制:比如我们选择的函数必须能接受其括号内函数的返回值;使用的函数规定必须参数为空或者为一个参数等 例题: <?…...

Python GUI开发必看:Tkinter Button控件使用详解
Button(按钮)组件用于实现各种各样的按钮。 Button组件可以包含文本或图像,你可以将一个Python的函数或方法与之相关联,当按钮被按下时,对应的函数或方法将被自动执行。 Button组件仅能显示单一字体的文本,…...
上海市计算机学会竞赛平台2024年7月月赛丙组得分排名
题目描述 给定 nn 名学生的考试得分,这些学生的学号为 11 到 nn,其第 ii 号学生的得分为 aiai,请将这些学生按照分数从大到小的顺序排列并输出学号序列。 若两个学生得分相同,则先输出较小的学号。 输入格式 第一行…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...