从内存流C#创建Zip文件
本文关键字:Zip 文件 创建 内存 | 更新日期: 2023-09-27 18:30:11
基本上,用户应该能够点击一个链接并下载多个pdf文件。但问题是我不能在服务器或任何地方创建文件。一切都必须在记忆中。
我可以将内存流和Response.Flush()创建为pdf,但如何在不创建文件的情况下压缩多个内存流。
这是我的代码:
Response.ContentType = "application/zip";
// If the browser is receiving a mangled zipfile, IIS Compression may cause this problem. Some members have found that
// Response.ContentType = "application/octet-stream" has solved this. May be specific to Internet Explorer.
Response.AppendHeader("content-disposition", "attachment; filename='"Download.zip'"");
Response.CacheControl = "Private";
Response.Cache.SetExpires(DateTime.Now.AddMinutes(3)); // or put a timestamp in the filename in the content-disposition
byte[] abyBuffer = new byte[4096];
ZipOutputStream outStream = new ZipOutputStream(Response.OutputStream);
outStream.SetLevel(3);
#region Repeat for each Memory Stream
MemoryStream fStream = CreateClassroomRoster();// This returns a memory stream with pdf document
ZipEntry objZipEntry = new ZipEntry(ZipEntry.CleanName("ClassroomRoster.pdf"));
objZipEntry.DateTime = DateTime.Now;
objZipEntry.Size = fStream.Length;
outStream.PutNextEntry(objZipEntry);
int count = fStream.Read(abyBuffer, 0, abyBuffer.Length);
while (count > 0)
{
outStream.Write(abyBuffer, 0, count);
count = fStream.Read(abyBuffer, 0, abyBuffer.Length);
if (!Response.IsClientConnected)
break;
Response.Flush();
}
fStream.Close();
#endregion
outStream.Finish();
outStream.Close();
Response.Flush();
Response.End();
这会创建一个zip文件,但里面没有文件
我正在使用使用iTextSharp.text-用于创建pdf使用ICSharpCode.SharpZipLib.Zip-用于压缩
谢谢,Kavita
此链接描述如何使用SharpZipLib从MemoryStream创建zip:https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#wiki-主持人记忆。使用这个和iTextSharp,我能够压缩在内存中创建的多个PDF文件。
这是我的代码:
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
byte[] bytes = null;
// loops through the PDFs I need to create
foreach (var record in records)
{
var newEntry = new ZipEntry("test" + i + ".pdf");
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
bytes = CreatePDF(++i);
MemoryStream inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
}
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return File(outputMemStream.ToArray(), "application/octet-stream", "reports.zip");
CreatePDF方法:
private static byte[] CreatePDF(int i)
{
byte[] bytes = null;
using (MemoryStream ms = new MemoryStream())
{
Document document = new Document(PageSize.A4, 25, 25, 30, 30);
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
document.Add(new Paragraph("Hello World " + i));
document.Close();
writer.Close();
bytes = ms.ToArray();
}
return bytes;
}
下面的代码是从azure blob存储中的目录中获取文件,合并到zip中,然后再次将其保存在azure blob存储器中。
var outputStream = new MemoryStream();
var archive = new ZipArchive(outputStream, ZipArchiveMode.Create, true);
CloudBlobDirectory blobDirectory = appDataContainer.GetDirectoryReference(directory);
var blobs = blobDirectory.ListBlobs();
foreach (CloudBlockBlob blob in blobs)
{
var fileArchive = archive.CreateEntry(Path.GetFileName(blob.Name),CompressionLevel.Optimal);
MemoryStream blobStream = new MemoryStream();
if (blob.Exists())
{
blob.DownloadToStream(blobStream);
blobStream.Position = 0;
}
var open = fileArchive.Open();
blobStream.CopyTo(open);
blobStream.Flush();
open.Flush();
open.Close();
if (deleteBlobAfterUse)
{
blob.DeleteIfExists();
}
}
archive.Dispose();
CloudBlockBlob zipBlob = appDataContainer.GetBlockBlobReference(zipFile);
zipBlob.UploadFromStream(outputStream);
需要名称空间:
- System.IO.Compression
- System.IO.Compression.ZipArchive
- Microsoft.Azure.Storage
- Microsoft.Azure.Storage.Blob
此代码将帮助您通过多个pdf文件创建Zip,您将从下载链接中获得每个文件。
using (var outStream = new MemoryStream())
{
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
for (String Url in UrlList)
{
WebRequest req = WebRequest.Create(Url);
req.Method = "GET";
var fileInArchive = archive.CreateEntry("FileName"+i+ ".pdf", CompressionLevel.Optimal);
using (var entryStream = fileInArchive.Open())
using (WebResponse response = req.GetResponse())
{
using (var fileToCompressStream = response.GetResponseStream())
{
entryStream.Flush();
fileToCompressStream.CopyTo(entryStream);
fileToCompressStream.Flush();
}
}
i++;
}
}
using (var fileStream = new FileStream(@"D:'test.zip", FileMode.Create))
{
outStream.Seek(0, SeekOrigin.Begin);
outStream.CopyTo(fileStream);
}
}
需要的命名空间:System.IO.Compression;System.IO.Compression.ZipArchive
下面是使用存在于ICSharpCode.SharpZipLib dll中的ZipOutputStream类在MemoryStream中创建zip文件的代码。
FileStream fileStream = File.OpenRead(@"G:'1.pdf");
MemoryStream MS = new MemoryStream();
byte[] buffer = new byte[fileStream.Length];
int byteRead = 0;
ZipOutputStream zipOutputStream = new ZipOutputStream(MS);
zipOutputStream.SetLevel(9); //Set the compression level(0-9)
ZipEntry entry = new ZipEntry(@"1.pdf");//Create a file that is needs to be compressed
zipOutputStream.PutNextEntry(entry);//put the entry in zip
//Writes the data into file in memory stream for compression
while ((byteRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
zipOutputStream.Write(buffer, 0, byteRead);
zipOutputStream.IsStreamOwner = false;
fileStream.Close();
zipOutputStream.Close();
MS.Position = 0;
我使用了这个线程中的信息,但决定发布端到端代码,因为它包含了下载后端服务器生成的zip文件的所有元素。
前端javascript Angular 12
`
export class downloadDocs{
fileName:string = '';
docs:string[] = [];
}
let docs = new downloadDocs();
//do some code to put names in docs.docs;
docs.fileName = 'download.zip';
this.http.post('api/docs/download', docs,
{ responseType: 'arraybuffer' }).subscribe(zip => {
let blob = new Blob([zip], { type: "application/octetstream" });
let url = window.URL || window.webkitURL;
let link = url.createObjectURL(blob);
let a = $("<a />");
a.attr("download", this.baseFileName() + '.zip');
a.attr("href", link);
$("body").append(a);
a[0].click();
$("body").remove(a);
},
error => {
//however you handle errors
}
`Azure应用服务中的web api核心5 C#后端。全内存解决方案之所以有效,是因为我根本不需要使用任何文件资源。使用了SharpLibZip软件包。
`
''drives me nuts in code examples nobody includes the libraries
''spend lot of time hunting down namespaces
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.AspNetCore.Http;
public class DownloadDocs{
public string FileName = "";
public List<string> Docs = new List<string>();
}
[Route("/api/docs/download")]
[HttpPost]
public async Task<ActionResult> ApiDownloadDocs([FromBody] DownloadDocs docs)
{
try
{
var stream = await this.ReturnZipFile(docs.Docs);
return File(stream, "application/octet-stream", docs.FileName);
}
catch (Exception e)
{
var msg = $"Docs Download error: {e.Message}";
return Problem(msg);
}
}
private async Task<MemoryStream> ReturnZipFile(List<string> files)
{
var stream = new MemoryStream();
stream.Position = 0;
var zipOutputStream = new ZipOutputStream(stream);
zipOutputStream.SetLevel(4); //Set the compression level(0-9)
foreach (let doc in files)
{
var docStream = new MemoryStream();
docStream = await this.GetPdfMemoryStream(doc);
byte[] buffer = new byte[docStream.Length];
int byteRead = 0;
ZipEntry entry = new ZipEntry(doc + ".pdf");
zipOutputStream.PutNextEntry(entry);
while ((byteRead = docStream.Read(buffer, 0, buffer.Length)) > 0)
zipOutputStream.Write(buffer, 0, byteRead);
docStream.Close();
}
zipOutputStream.Finish();
//zipOutputStream.Close(); //this also closed the output stream and made it worthless
stream.Position = 0;
return stream;
}
`
Sql Server代码从表中读取blob,然后将其作为字节数组和内存流返回。
`
public async Task<byte[]> GetPdfBytes(string uuid)
{
byte[] fileBytes = null;
var conn = new SqlConnection(connectionString);
await conn.OpenAsync();
string sql = $"SELECT CONVERT(varbinary(max),BLOB) FROM DOC_BLOBS WHERE UUID = '{uuid}'";
using (var cmd = new SqlCommand(sql, conn))
{
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
fileBytes = (byte[])reader[0];
}
}
}
return fileBytes;
}
public async Task<MemoryStream> GetPdfMemoryStream(string uuid)
{
return new MemoryStream(await GetPdfBytes(uuid));
}
`
您可以生成pdf文件并将其存储在IsolatedStorageFileStream中,然后可以从该存储中压缩内容。