나는 Asp.Net Mvc 응용 프로그램이 있습니다. 이 응용 프로그램에서는 데이터베이스에서 Excel 파일 (OpenXml SDK 포함)로 데이터를 다운로드 할 수있는 기능이 있습니다. 이제 작동합니다. 그러나 데이터가 크면 사용자 요청에서 다운로드 창이있는 응답 시간은 10 분 이상이됩니다. 이는 두 가지 긴 프로세스 때문입니다.OpenXml 및 HttpResponse.OutputStream
- MSSQL 서버에서 데이터를 가져 오는 중입니다.
- 서버의 메모리에 Excel 문서 생성. (Excel 문서가 완료된 경우에만 다운로드가 시작됩니다.)
첫 번째 문제는 DataReader를 사용하여 해결되었습니다. 이제 엑셀 파일 생성은 사용자 요청이 웹 서버에 도착한 직후에 시작됩니다.
두 번째 문제를 해결하려면 HttpResponse.OutputStream에서 Excel 문서를 생성해야하지만이 스트림은 Seekable이 아니며 시작하기 전에 생성이 실패합니다.
누구나이 문제를 해결하는 데 도움이되는 해결 방법을 알고 있습니까? 내 생성 기능의
샘플 : (HttpResponse.OutputStream 작업을위한)
public void GenerateSpreadSheetToStream(IDataReader dataReader, Stream outputStream)
{
var columnCaptions = FillColumnCaptionsFromDataReader(dataReader.GetSchemaTable());
//fails on next line with exception "Cannot open package because FileMode or FileAccess value is not valid for the stream."
using (var spreadsheetDocument = SpreadsheetDocument.Create(outputStream, SpreadsheetDocumentType.Workbook))
{
spreadsheetDocument.AddWorkbookPart();
var workSheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
OpenXmlWriter writer;
using (writer = OpenXmlWriter.Create(workSheetPart))
{
using (writer.Write(new Worksheet()))
{
using (writer.Write(new SheetData()))
{
using (writer.Write(w =>
w.WriteStartElement(new Row(), new[] {new OpenXmlAttribute("r", null, 1.ToString(CultureInfo.InvariantCulture))})))
{
var cells =
columnCaptions.Select(caption => new Cell()
{
CellValue = new CellValue(caption.Item2),
DataType = CellValues.String
});
foreach (var cell in cells)
{
writer.WriteElement(cell);
}
}
var i = 2;
while (dataReader.Read())
{
var oxa = new[] { new OpenXmlAttribute("r", null, i.ToString(CultureInfo.InvariantCulture)) };
using (writer.Write(w => w.WriteStartElement(new Row(), oxa)))
{
var cells =
columnCaptions.Select(
(c, j) =>
new Cell
{
CellValue = new CellValue(dataReader[c.Item1].ToString()),
DataType = CellValues.String,
CellReference = new StringValue(GetSymbolByCellNumber(j))
});
foreach (var cell in cells)
{
writer.WriteElement(cell);
}
}
i++;
}
}
}
}
using (writer = OpenXmlWriter.Create(spreadsheetDocument.WorkbookPart))
{
using (writer.Write(new Workbook()))
{
using (writer.Write(new Sheets()))
{
var sheet = new Sheet
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(workSheetPart),
SheetId = 1,
Name = SheetName
};
writer.WriteElement(sheet);
}
}
}
}
}
private static string GetSymbolByCellNumber(int number)
{
var r = number/26;
var s = (char) ((number%26) + 65);
return new string(s, r);
}
내 FileStreamResultWithTransformation :
public class FileStreamResultWithTransformation : FileResult
{
private readonly Action<Stream> _action;
public FileStreamResultWithTransformation(Action<Stream> action, string contentType, string fileName) : base(contentType)
{
_action = action;
FileDownloadName = fileName;
}
protected override void WriteFile(HttpResponseBase response)
{
response.BufferOutput = false;
_action(response.OutputStream); ->> it fails there
}
}
스택 트레이스 :
[IOException가 : 열 수 없습니다 패키지 때문에하는 FileMode 또는 FileAccess 값이 스트림에 유효하지 않습니다.] System.IO.Packaging.Package.Val idetModeAndAccess (스트림 s, FileMode 모드, FileAccess 액세스) +784533 System.IO.Packaging.Package.Open (스트림 스트림, FileMode packageMode, FileAccess packageAccess, 부울 스트리밍) +89 System.IO.Packaging.Package.Open 스트림 packageMode하는 FileMode, FileAccess packageAccess) +10 DocumentFormat.OpenXml.Packaging.OpenXmlPackage.CreateCore (스트림 스트림) 192 DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Create (스트림 스트림 SpreadsheetDocumentType 유형 부울 자동 저장) 215 DOCUMENTFORMAT .OpenXml.Packaging.SpreadsheetDocument.Create (Stream stream, SpreadsheetDocumentType type) +44 d : \ Work \ Epsilon \ development \ Web \ trunk \ Sources \에있는 GenerateSpreadSheetToStream (IDataReader dataReader, Stream outputStream) Epsilon.DocumentGenerator \ XlsXGenerator.cs : 119
나는 얼마 전에 일하게하려고 노력했다. 나는 그 당시의 길을 찾지 못했고'MemoryStream'과'.WriteTo (response.OutputStream)'을 고수해야했다. – tpeczek
이것은 내 두 번째 문제를 해결하지 못합니다 (Excel 문서가 완료된 경우에만 다운로드가 시작됩니다). –
나는 이것이 대답이 아니라, 단지 의견이라는 것을 알고있다. – tpeczek