2016-11-29 1 views
0

내 웹 사이트에서 사용자가 특정 버튼을 클릭하면 많은 파일이 zip에 보관되어 전송됩니다. 파일 자체는 세 번째 파트에서 생성되며 URL 만 있습니다. 부분적으로 성공했지만 문제가 있습니다.zip 파일을 생성 중일 때 보내기

먼저 압축 할 파일이 많으면 먼저 서버 응답이 느리므로 zip 파일을 작성한 다음 전송합니다. 심지어 잠시 후에 충돌 할 수 있습니다 (특히, "오버플로 또는 산술 연산의 언더 플로"오류가 발생 함).

둘째, 지금은 zip 아카이브가 완료되면 파일이 전송됩니다. 다운로드가 즉시 시작되기를 바랍니다. 즉, 사용자가 대화 상자에서 "저장"을 클릭하자마자 데이터가 전송되기 시작하고 zip 파일이 "즉석에서"만들어 지므로 전송이 계속됩니다. 일부 웹 사이트에서 해당 기능을 보았습니다. 예를 들면 다음과 같습니다. http://download.muuto.com/

문제는 그 방법을 알 수 없습니다. Creating a dynamic zip of a bunch of URLs on the fly 를 그리고이 블로그 게시물에서 :

이 질문의 코드의 일부를 사용하고 http://dejanstojanovic.net/aspnet/2015/march/generate-zip-file-on-the-fly-in-aspnet-mvc-application/

자체가 창조와 ASP.NET MVC 컨트롤러 메서드에서 반환되는 zip 파일.

응답의 OutputStream과 버퍼링 조금 하구에 의해 확인
using ICSharpCode.SharpZipLib.Zip; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Web; 
using System.Web.Mvc; 

namespace MyProject.Controllers 
{ 
    public class MyController : Controller 
    {   
     public ActionResult DownloadFiles() 
     { 
      var files = SomeFunction(); 

      byte[] buffer = new byte[4096]; 

      var baseOutputStream = new MemoryStream(); 
      ZipOutputStream zipOutputStream = new ZipOutputStream(baseOutputStream); 
      zipOutputStream.SetLevel(0); //0-9, 9 being the highest level of compression 
      zipOutputStream.UseZip64 = UseZip64.Off; 
      zipOutputStream.IsStreamOwner = false; 

      foreach (var file in files) 
      { 
       using (WebClient wc = new WebClient()) 
       { 
        // We open the download stream of the file 
        using (Stream wcStream = wc.OpenRead(file.Url)) 
        { 
         ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName)); 
         zipOutputStream.PutNextEntry(entry); 

         // As we read the stream, we add its content to the new zip entry 
         int count = wcStream.Read(buffer, 0, buffer.Length); 
         while (count > 0) 
         { 
          zipOutputStream.Write(buffer, 0, count); 
          count = wcStream.Read(buffer, 0, buffer.Length); 
          if (!Response.IsClientConnected) 
          { 
           break; 
          } 
         } 
        } 
       } 
      } 
      zipOutputStream.Finish(); 
      zipOutputStream.Close(); 

      // Set position to 0 so that cient start reading of the stream from the begining 
      baseOutputStream.Position = 0; 

      // Set custom headers to force browser to download the file instad of trying to open it 
      return new FileStreamResult(baseOutputStream, "application/x-zip-compressed") 
      { 
       FileDownloadName = "Archive.zip" 
      }; 
     } 
    } 
} 
+0

가능한 중복 여기 내 코드입니다. net with SharpZipLib] (http://stackoverflow.com/questions/626196/streaming-a-zip-file-over-http-in-net-with-sharpziplib) –

+0

확실히 관련이 있지만 (같은 목표), 중복되지는 않습니다. 다른 접근 방식 인 MVC 컨트롤러에서이 작업을 시도하고 있습니다. 나는'BufferOutput = false'을 다른 방법으로 사용하려했지만 많이 변하지 않는 것 같습니다. – Ogier

+0

다르지 않다. 스트림을 매개 변수로 받아들이는'FileResult'를 반환 할 수 있습니다 –

답변

1

, 나는 해결책에 도착했습니다 : [가에서 HTTP를 통해 압축 파일을 스트리밍의

using ICSharpCode.SharpZipLib.Zip; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Web; 
using System.Web.Mvc; 

namespace MyProject.Controllers 
{ 
    public class MyController : Controller 
    {   
     public ActionResult DownloadFiles() 
     { 
      var files = SomeFunction(); 

      // Disable Buffer Output to start the download immediately 
      Response.BufferOutput = false; 

      // Set custom headers to force browser to download the file instad of trying to open it 
      Response.ContentType = "application/x-zip-compressed"; 
      Response.AppendHeader("content-disposition", "attachment; filename=Archive.zip"); 

      byte[] buffer = new byte[4096]; 

      ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream); 
      zipOutputStream.SetLevel(0); // No compression 
      zipOutputStream.UseZip64 = UseZip64.Off; 
      zipOutputStream.IsStreamOwner = false; 

      try 
      { 
       foreach (var file in files) 
       { 
        using (WebClient wc = new WebClient()) 
        { 
         // We open the download stream of the image 
         using (Stream wcStream = wc.OpenRead(file.Url)) 
         { 
          ZipEntry entry = new ZipEntry(ZipEntry.CleanName(file.FileName)); 
          zipOutputStream.PutNextEntry(entry); 

          // As we read the stream, we add its content to the new zip entry 
          int count = wcStream.Read(buffer, 0, buffer.Length); 
          while (count > 0) 
          { 
           zipOutputStream.Write(buffer, 0, count); 
           count = wcStream.Read(buffer, 0, buffer.Length); 
           if (!Response.IsClientConnected) 
           { 
            break; 
           } 
          } 
         } 
        } 
       } 
      } 
      finally 
      { 
       zipOutputStream.Finish(); 
       zipOutputStream.Close(); 
      } 

      return new HttpStatusCodeResult(HttpStatusCode.OK); 
     } 
    } 
} 
관련 문제