2017-09-21 9 views
2

큰 XML 파일 아카이브를 호스팅하는 서버가 있고 API가 zip 내에 요청 된 파일을 검색합니다. 11 개 이하의 파일을 선택하면 우편 번호가 올바르게 반환됩니다. 좀 더를 검색 할 경우에, 나는 우편 열려고 시도 할 다음과 같은 오류가 나타납니다. "윈도우 폴더를 열 수 없습니다 압축 (ZIP) 폴더가 잘못 입니다."zip으로 파일을 다운로드하면 ASP.NET MVC에서 손상된 zip이 발생합니다.

다음은 데이터 클래스 및 방법은 우편을 만들 수 있습니다

//Archive file containing filename and content as memory stream 
public class ArchiveFile { 
    public string FileName; 
    public System.IO.MemoryStream FileContent; 
} 

//Method to retrieve archive files and zip them 
public static System.IO.MemoryStream GetFilesAsZip (string[] arrFileNames) { 
    MemoryStream zipStream = null; 
    using (zipStream = new MemoryStream()) { 
     // Retrieve files using above method 
     ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames); 
     // Initialize new ZipArchive on the return object's MemoryStream property 
     using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) { 
      // Write file entries into archive 
      foreach (ArchiveFile dataFile in retrievedFiles) { 
       if (dataFile.FileContent != null) { 
        // Create new ZipArchiveEntry with content 
        ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName); 
        dataFile.FileContent.WriteTo(zipEntry.Open()); 
       }//end if 
      } // end foreach 
     } //end using 
    } //end using 
    return zipStream; 
}//end method 

//API to return content to user as an MVC File Content Result 
[HttpGet] 
public ActionResult DownloadFiles (string [] fileNames) { 
    FileContentResult data = new FileContentResult(GetFiles(fileNames).GetBuffer(), “application/zip”) { FileDownloadName = “files.zip” }; 
    return data; 
} //end method 

부패가 메모리 스트림에 쓸 때 공간 할당 함께 할 수있는 뭔가가있을 수 있습니다. 나는 "성공한"모든 지퍼 (11 개 이하의 파일)의 크기가 259KB 였지만, "실패한"지퍼 (11 개 이상의 파일)는 크기가 517KB이고 크기가 더 큰 일부 지퍼는 1034KB였습니다. 그것은 특히 25 파일 크기의 파일이 259 KB의 압축 결과를 가져 오지만 12 파일의 압축 파일은 517 KB의 압축 결과를 가져 오기 때문에이 파일들이 모두 258.5 KB의 배수라는 것은 너무 우연한 일치입니다.

무엇이 될 수 있는지에 대한 통찰력이 있으십니까?

+0

어떻게 든 XML 파일을 공유 할 수 있습니까? – Isma

+0

불행히도 나는 개인 정보를 포함 할 수 없다. – crodriguez

+0

MemoryStream을 올바르게 사용하고 있지 않습니다. 대신에 newStream을 사용하는 대신 새로운 바이트 배열을 반환하고이를 반환합니다. 그 zipStream.ToArray() <- 제대로 처리하지 못하는 MemoryStream 대신에 반환해야하는 바이트 배열에 저장하십시오. –

답변

0

나는 과거에 성공했습니다. return File(fileLocation, "application/zip", fileName); 여기서 fileLocation은 폴더의 경로이고 fileName은 실제 폴더의 이름입니다. ActionResult에서이 작업을 올바르게 수행 할 수 있습니다. 컨트롤러에서

+0

예 다른 질문에 대한 전체 예제를 함께 작성합니다 –

+0

나는 이것이 나를 위해 작동하지 않을까 두려워요. zip은 파일 조합이 무엇이든 동적으로 생성되므로 디스크에 저장되지 않습니다. – crodriguez

1

ASP.Net Core API Controller returns corrupted excel file

수익이

return new FileResult("demo.zip", Path.Combine(sWebRootFolder, sFileName), "application/zip"); 

은 당신의 코드가는 CH 할 수 있어야한다

public byte[] GetFilesAsZip (string[] arrFileNames) { 
    byte[] buffer = null; 
    using (MemoryStream zipStream = new MemoryStream()) { 
     // Retrieve files using above method 
     ArchiveFile[] retrievedFiles = GetFilesFromArchive(arrFileNames); 
     // Initialize new ZipArchive on the return object's MemoryStream property 
     using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update, leaveOpen: true)) { 
      // Write file entries into archive 
      foreach (ArchiveFile dataFile in retrievedFiles) { 
       if (dataFile.FileContent != null) { 
        // Create new ZipArchiveEntry with content 
        ZipArchiveEntry zipEntry = archive.CreateEntry(dataFile.FileName); 
        dataFile.FileContent.WriteTo(zipEntry.Open()); 
       }//end if 
      } // end foreach 
     } //end using 
     buffer = zipStream.ToArray(); 
    } //end using 
    return buffer; 
}//end method 

리팩토링

public class FileResult : ActionResult 
    { 
     public FileResult(string fileDownloadName, string filePath, string contentType) 
     { 
      FileDownloadName = fileDownloadName; 
      FilePath = filePath; 
      ContentType = contentType; 
     } 

     public string ContentType { get; private set; } 
     public string FileDownloadName { get; private set; } 
     public string FilePath { get; private set; } 

     public async override Task ExecuteResultAsync(ActionContext context) 
     { 
      var response = context.HttpContext.Response; 
      response.ContentType = ContentType; 
      context.HttpContext.Response.Headers.Add("Content-Disposition", new[] { "attachment; filename=" + FileDownloadName }); 
      using (var fileStream = new FileStream(FilePath, FileMode.Open)) 
      { 
       await fileStream.CopyToAsync(context.HttpContext.Response.Body); 
      } 
     } 
    } 

이 코드를 추가 이 번호로

FileContentResult data = new FileContentResult(GetFiles(fileNames), “application/zip”) { FileDownloadName = “files.zip” };