NET8环境WebAPI实现文件的压缩及下载

1、文件下载的原理

在实际应用环境中,文件的下载是一个特别常见的需求。为了传输文件的大小,往往需要对文件进行压缩,因此就涉及到文件的压缩及文件的下载,具体步骤有5步。(1)、请求端发出文件的请求。这个可以根据实际需求,使用get/post及参数,发起一个请求。(2)、服务器收到请求后,会根据需求生成(或者准备)相关文件(最常用的例子就是:患者通过医院App下载处方、门诊记录单、诊断证明书之类)【这一步往往是偏向业务相关】。(3)然后将这些生成的文件,压缩成zip文件格式。(4)、服务端返回数据。(5)、客户端收到数据后,解析Response中的Stream,并使用FileStream将文件存储到本地。
具体的原理如下图所示
文件下载的原理

2、具体实现

2.1 提前准备

我们提前准备了文件(这步主要是模拟实际业务中生成的文件夹及文件)。在fhirs文件夹下有一个index.xml文件和emrfhirs文件夹,并且在emrfhirs文件夹内有001fhir.json002fhir.json003fhir.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-stream
        var 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、get
        request.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 密码保护

.NETSystem.IO.Compression命名空间不支持为ZIP文件添加密码保护。如果你需要这个功能,你可能需要使用第三方库,如DotNetZip

4.3.3 进度反馈

在压缩或解压大文件时,提供进度反馈是一个很好的用户体验。然而,System.IO.Compression命名空间并没有直接提供进度反馈的机制。你可以通过计算处理的文件大小与总大小来估算进度,并使用例如IProgress<T>接口来报告进度。

5、参考资料

这篇文章主要参考了这篇文章:NET环境下使用原生方法实现文件压缩与解压

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值