コンポーネント
- asp.net Web フォーム上のいくつかの値を持つフォーム
- ファイル入力 (asp:File などではなく、標準の HTML5)
- 私が理解しているbluimp jQueryファイルアップローダーは、この種のことには非常に優れていますが、使用したことはありません
- MVC4 WebAPI コントローラー
- Web フォームの JavaScript のノックアウト JS ビューモデル (ここでは重要ではありませんが、言及する価値があります)。
目標
基本的に、検証、処理、ビジネス オブジェクトへの変換、および JSON アイテムとしての返還のためにアップロードする小さな Excel シートがあります。
私は次のことが起こることを望みます:
- ユーザーがフォームなどにデータを入力します。
- ユーザーがフォームにファイルを追加します。
- ファイルは、(bluimp コントロールを使用して) MVC コントローラーに、テキストを含むフォーム フィールド値と共に自動的にアップロードされます。
次に、コントローラーで、
- 渡されたテキスト フィールドはサニタイズ/検証済みです。
- ファイルはメモリに処理されます
- (これらは非常に小さく、数も少ないので、ファイル システムにアクセスする必要はないと思いますか?)
- ファイルは
FileProcessor
、ストリームを使用する を使用して処理され、テキスト フィールドを使用してインスタンス化されます。
問題
私はこれらのコンポーネントをまだ十分に理解していないので、単純な間違いを犯しているのか、それとも複雑な間違いを犯しているのかを理解できません。
私がこれまでに持っているもの
注: 明示的にクリックしてファイルを送信するボタンを使用してこれを試みていましたが、将来的には自動的に実行したいと考えています。
ファイルを送信するフォーム:
<form id="fileUploadForm" action="/api/InvoiceDetailsFile/PostForProcessing" method="POST" enctype="multipart/form-data">
<input type ="hidden" name="clientSiteId" id="clientSiteId" value="3"/>
<input type="file" id="inpFile" required="required"/>
<input type ="button" id="btnSendFile" title="Send File" value="Send File"/>
</form>
アップロード用の JavaScript (これは非常に間違っている可能性があります):
$(document).ready(function () {
'use strict';
var btnSendFile = $("#btnSendFile");
var frmFileUpload = $("#fileUploadForm");
btnSendFile.click(function () {
console.log('send button clicked');
frmFileUpload.fileupload("send");
});
});
アップロードを処理する WebAPI コントローラー (これは非常に間違っている可能性があります):
[HttpPost]
public Task<List<IInvoiceDetailItem>> PostForProcessing(int clientSiteId)
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var results = new List<IInvoiceDetailItem>();
var streamProvider = new MultipartMemoryStreamProvider();
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t =>
{
// can I only expect 1 item here?
foreach (var item in streamProvider.Contents)
{
// if it's an Excel Sheet
if (item.IsMimeMultipartContent("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
{
try {
var workbook = new XLWorkbook(item.ReadAsStreamAsync().Result);
// clientSiteId here comes from form value (via constructor?), ContextUser comes from a BaseApi.
var processor =
new InvoiceProcessorFactory(clientSiteId, ContextUser)
.GetInvoiceProcessorInstance();
results = processor.ProcessInvoice(workbook).ToList();
}
catch (Exception ex)
{
throw new HttpException(Convert.ToInt32(HttpStatusCode.InternalServerError), "Well, this is a bummer. The invoice processor failed. Please see the inner exception.", ex);
}
}
}
return results;
});
return task;
}
進行に合わせてコード サンプルを更新し続けますが、苦労することはわかっているので、遅かれ早かれ公開したかったのです。