programing

스트림에서 Zip 파일 생성 및 다운로드

i4 2023. 9. 3. 12:11
반응형

스트림에서 Zip 파일 생성 및 다운로드

저는 데이터 테이블을 xml로 변환한 다음 DotNetZip을 사용하여 압축하고 싶습니다.마지막으로 사용자는 Asp를 통해 다운로드할 수 있습니다.인터넷 웹 페이지.아래의 내 코드

    dt.TableName = "Declaration";

    MemoryStream stream = new MemoryStream();
    dt.WriteXml(stream);

    ZipFile zipFile = new ZipFile();
    zipFile.AddEntry("Report.xml", "", stream);
    Response.ClearContent();
    Response.ClearHeaders();
    Response.AppendHeader("content-disposition", "attachment; filename=Report.zip");

    zipFile.Save(Response.OutputStream);
    //Response.Write(zipstream);
    zipFile.Dispose();

zip 파일의 xml 파일이 비어 있습니다.

두 가지.먼저, 현재 보유한 코드 설계를 유지하는 경우 항목에 쓰기 전에 MemoryStream에서 Seek()를 수행해야 합니다.

dt.TableName = "Declaration"; 

MemoryStream stream = new MemoryStream(); 
dt.WriteXml(stream); 
stream.Seek(0,SeekOrigin.Begin);   // <-- must do this after writing the stream!

using (ZipFile zipFile = new ZipFile())
{
  zipFile.AddEntry("Report.xml", "", stream); 
  Response.ClearContent(); 
  Response.ClearHeaders(); 
  Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

  zipFile.Save(Response.OutputStream); 
}

이 디자인을 유지하더라도 Dispose()를 호출하는 대신에 제가 보여드린 것처럼 모든 DotNetZip 예제에서 설명한 바와 같이 use() 절을 제안합니다.using() 절은 실패 시 더욱 신뢰할 수 있습니다.

이제 AddEntry()를 호출하기 전에 MemoryStream에서 검색해야 하는 이유가 무엇인지 궁금하실 수 있습니다.그 이유는 AddEntry()는 위치가 중요한 스트림을 통과하는 발신자를 지원하도록 설계되었기 때문입니다.이 경우 호출자는 스트림의 현재 위치를 사용하여 스트림에서 항목 데이터를 읽어야 합니다.AddEntry()는 이를 지원합니다.따라서 AddEntry()를 호출하기 전에 스트림에서 위치를 설정합니다.

그러나 더 나은 옵션은 쓰기 위임을 수락하는 AddEntry()의 오버로드를 사용하도록 코드를 수정하는 것입니다.데이터셋을 zip 파일에 추가하기 위해 특별히 설계되었습니다.원래 코드는 데이터 세트를 메모리 스트림에 쓴 다음 스트림을 찾고 스트림의 내용을 zip에 씁니다.데이터를 한 번 작성하면 더 빠르고 쉽게 작성할 수 있으며, 이는 쓰기 위임자가 허용하는 작업입니다.코드는 다음과 같습니다.

dt.TableName = "Declaration"; 
Response.ClearContent(); 
Response.ClearHeaders(); 
Response.ContentType = "application/zip";
Response.AppendHeader("content-disposition", "attachment; filename=Report.zip"); 

using(Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile())
{
    zipFile.AddEntry("Report.xml", (name,stream) => dt.WriteXml(stream) );
    zipFile.Save(Response.OutputStream); 
}

그러면 데이터 세트가 zip 파일의 압축된 스트림에 직접 기록됩니다.매우 효율적입니다!더블 버퍼링은 안 됩니다.익명 대리인은 ZipFile 시간에 호출됩니다.저장().쓰기(+압축)는 하나만 수행됩니다.

메모리 스트림을 닫지 않은 이유는 무엇입니까, 저는 그것을 포장할 것입니다.using조항, 동일하게 말할 수 있습니다.zipFile 한또dt데이터 테이블인 것 같습니다...행이 있는지 확인하기 위해 오류 검사를 수행합니다. 아래 코드를 참조하십시오.

dt.표 이름 = "선언";
if (dt)행!= null &gt;&dt.Rows.Count >= 1){(MemoryStream 스트림 = 새 MemoryStream() 사용{dt의WriteXml(스트림);
치소/마이카엘 감사합니다.개울.Seek(0, Seek Origin.시작);//
(ZipFile zipFile = newZipFile() 사용{zipFile.엔트리 추가("Report.xml", "" 스트림); 
대답.내용 지우기();대답.머리글 지우기();대답.AppendHeader("content-disposition", "평가; filename=Report.zip");
//zipFile.저장(응답).출력 스트림);zipFile.저장(스트림);
코멘트 아웃/*대답.쓰기(zipstream); // <-------------------------------------------------------
*/}대답.쓰기(스트림);}}행 없음...신경쓰지 마...

편집: 이것을 다시 보고, 이오니아를 깨달았습니다.코드플렉스의 Ziplib이 사용되었습니다. 코드를 약간 바꿨습니다.zipFile.Save(Response.OutputStream);사용한zipFile.Save(stream);사용stream의 예MemoryStream를 사용하여 수업하고 작성합니다.Response.Write(stream);.

편집 #2: 명백한 결점을 지적해 준 Cheeso + Mikael 덕분에 - 저는 1마일 떨어진 곳에서 그것을 놓쳤고 스트림이 끝에 있다는 것을 깨달을 때까지 그들의 의견을 이해하지 못했습니다...

지퍼를 내리기 전에 개울물을 내려보셨습니까?

dt.WriteXml(stream);
stream.Flush();
ZipFile zipFile = new ZipFile();

알겠습니다. 여기까지 오는 것 같지는 않아서 디버깅을 좀 더 시작해보셔야 합니다.

코드를 업데이트하여 다음을 수행합니다.

dt.WriteXml(stream);
stream.Seek(0, SeekOrigin.Begin);
File.WriteAllBytes("c:\test.xml", stream.GetBuffer());

유효한 XML 파일이 있는지 확인합니다.그러면 ZipFile에서도 동일한 작업을 수행합니다.로컬 파일에 저장합니다.xml 파일이 있는지 확인하고 xml 파일에 내용이 있는지 확인합니다.

이 방법이 효과가 있으면 응답으로 메모리 스트림만 다시 전송하여 효과가 있는지 확인합니다.

그러면 문제를 더 추적할 수 있습니다.

콘텐츠 추가머리글 입력:

Response.ContentType = "application/zip";

이렇게 하면 브라우저가 사용자가 보내는 내용을 탐지할 수 있습니다.

돌아오는 스트림도 다시 확인하십시오.아래의 예에서

zipFile.Save(Response.OutputStream);
Response.Write(zipstream);
zipFile.Dispose();

저장 방법을 사용하여 zipFile을 응답 스트림에 저장하지만 응답을 호출하는 경우도 마찬가지입니다.zipstream 변수를 사용하여()를 작성합니다.zipstream이란 무엇입니까?또한 빈 스트림이 아닌지 확인합니다.

스트림에서 zip 파일을 만들어 다운로드하는 중입니다.아래는 코드입니다.

FileStream stream=File.OpenRead(@"D:\FileDownLoad\DeskTop\1.txt");
MemoryStream MS=new MemoryStream();

ZipOutputStream zipOutputStream = new ZipOutputStream(MS);
zipOutputStream.SetLevel(9);
ZipEntry entry = new ZipEntry("1.txt");
zipOutputStream.PutNextEntry(entry);

byte[] buffer = new byte[stream.Length];
int byteRead = 0;

while ((byteRead = stream.Read(buffer, 0, buffer.Length)) > 0) 
    zipOutputStream.Write(buffer, 0, byteRead);

    zipOutputStream.IsStreamOwner = false;
    stream.Close();
    zipOutputStream.Close();
    MS.Position = 0;

    Response.ContentType = "application/application/octet-stream";
    Response.AppendHeader("content-disposition", "attachment; filename=\"Download.zip\"");
    Response.BinaryWrite(MS.ToArray());

이 코드는 스트림에서 파일을 다운로드하는 데 도움이 됩니다.

using (var outStream = new MemoryStream())
{
    using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
    {
        var fileInArchive = archive.CreateEntry("FileName.pdf", CompressionLevel.Optimal);
        using (var entryStream = fileInArchive.Open())
        using (WebResponse response = req.GetResponse())
        {
            using (var fileToCompressStream = response.GetResponseStream())
            {
                fileToCompressStream.CopyTo(entryStream);
            }
        }                       
    }
    using (var fileStream = new FileStream(@"D:\test.zip", FileMode.Create))
    {
        outStream.Seek(0, SeekOrigin.Begin);
        outStream.CopyTo(fileStream);
    }
}

필요한 네임스페이스:

using System.IO.Compression;
using System.IO.Compression.ZipArchive;

언급URL : https://stackoverflow.com/questions/2266204/creating-zip-file-from-stream-and-downloading-it

반응형