스트림에서 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 >&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
'programing' 카테고리의 다른 글
문자 입력 요소 내부의 글꼴 멋진 아이콘 (0) | 2023.09.08 |
---|---|
부트스트랩 모드: 함수가 아닙니다. (0) | 2023.09.08 |
Playground에서 비동기 콜백을 실행하는 방법 (0) | 2023.09.03 |
Oracle과 대체 스키마의 외부 키? (0) | 2023.09.03 |
$.ajax url을 사용하여 여러 매개 변수 전달 (0) | 2023.09.03 |