Excel をカスタム FileResult として返すアクションがあります。私のソリューションは、ClosedXmlライブラリ (内部的に OpenXml を使用) に基づいています。私の XlsxResult クラスは、サーバー上の読み取り専用の .xlsx ファイルをテンプレートとして使用します。次に、テンプレートをメモリ ストリームに渡します。メモリ ストリームは、ClosedXml で操作および保存されます。最後に、メモリ ストリームが応答に書き込まれます。
これは、Cassini と IIS Express の両方で正常に動作しますが、Azure にデプロイすると失敗し、エラーは発生しません。私が経験している唯一の影響は、サーバーに送信されたリクエストが応答を返さないことです。60分ほど経ってもまだ何かが起こるのを待っています...
私の行動:
[OutputCache(Location= System.Web.UI.OutputCacheLocation.None, Duration=0)]
public FileResult Export(int year, int month, int day) {
var date = new DateTime(year, month, day);
var filename = string.Format("MyTemplate_{0:yyyyMMdd}.xlsx", date);
//return new FilePathResult("~/Content/templates/MyTemplate.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
var result = new XlsxExportTemplatedResult("MyTemplate.xlsx", filename, (workbook) => {
var ws = workbook.Worksheets.Worksheet("My Export Sheet");
ws.Cell("B3").Value = date;
// Using a OpenXML's predefined formats (15 stands for date)
ws.Cell("B3").Style.NumberFormat.NumberFormatId = 15;
ws.Columns().AdjustToContents(); // You can also specify the range of columns to adjust, e.g.
return workbook;
});
return result;
}
私のファイル結果
public class XlsxExportTemplatedResult : FileResult
{
// default buffer size as defined in BufferedStream type
private const int BufferSize = 0x1000;
public static readonly string TEMPLATE_FOLDER_LOCATION = @"~\Content\templates";
public XlsxExportTemplatedResult(string templateName, string fileDownloadName, Func<XLWorkbook, XLWorkbook> generate)
: base("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
this.TempalteName = templateName;
this.FileDownloadName = fileDownloadName;
this.Generate = generate;
}
public string TempalteName { get; protected set; }
public Func<XLWorkbook, XLWorkbook> Generate { get; protected set; }
protected string templatePath = string.Empty;
public override void ExecuteResult(ControllerContext context) {
templatePath = context.HttpContext.Server.MapPath(System.IO.Path.Combine(TEMPLATE_FOLDER_LOCATION, this.TempalteName));
base.ExecuteResult(context);
}
//http://msdn.microsoft.com/en-us/library/office/ee945362(v=office.11).aspx
protected override void WriteFile(System.Web.HttpResponseBase response) {
FileStream fileStream = new FileStream(templatePath, FileMode.Open, FileAccess.Read);
using (MemoryStream memoryStream = new MemoryStream()) {
CopyStream(fileStream, memoryStream);
using (var workbook = new XLWorkbook(memoryStream)) {
Generate(workbook);
workbook.Save();
}
// At this point, the memory stream contains the modified document.
// grab chunks of data and write to the output stream
Stream outputStream = response.OutputStream;
byte[] buffer = new byte[BufferSize];
while (true) {
int bytesRead = memoryStream.Read(buffer, 0, BufferSize);
if (bytesRead == 0) {
// no more data
break;
}
outputStream.Write(buffer, 0, bytesRead);
}
}
fileStream.Dispose();
}
static private void CopyStream(Stream source, Stream destination) {
byte[] buffer = new byte[BufferSize];
int bytesRead;
do {
bytesRead = source.Read(buffer, 0, buffer.Length);
destination.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
}
だから私は何かが欠けています(どうやら私はそうです)。
ご注意ください:
- Windows Azure Tools 1.7 の RemoteAccess 機能を使用して確認したため、Azure から欠落している dll はありません。
- 私のエクスポートは、長時間実行される重いタスクではありません。
- テンプレート xlsx を使用して FilePathResult を返すようにアクションを変更すると、紺碧で動作しました。しかし、あなたが疑うかもしれないように、ファイルを返す前にファイルを処理する必要があります:-)
タンク。
更新: コードに広範囲にログインした後、ClosedXml の "Save" メソッド呼び出しで実行がエラーなしでハングします。しかし、まだエラーはありません。WADLogsTable からの抜粋:
- パスからテンプレート ファイルを開く: E:\sitesroot\0\Content\templates\MyTemplate.xlsx
- パスからテンプレートを開きました: E:\sitesroot\0\Content\templates\MyTemplate.xlsx
- テンプレートを編集可能なメモリ ストリームにコピーしました。コピーされたバイト: 15955、位置: 15955
- メモリ内の Excel ドキュメントを変更しました。
- ここでは、workbook.Save(); を呼び出すとハングします。これは ClosedXml メソッドの呼び出しです。