この問題に有効な解決策を見つけました。私のアップロードは次のように機能するようになりました。
ファイルを DataURL として FileReader に読み込みます
返された文字列をスライスし、各スライスをサーバーに送信してセッション変数に格納します
ファイル全体が送信されたら、別の Web サービスを呼び出します。この Web サービスは、スライスをつなぎ合わせて、結果をバイト配列に変換します。
バイト配列は、Azure のローカル ストレージにファイルとして保存されます。
最後に、ファイルはローカル ストレージから BLOB ストレージに転送されます
これはおそらく最善の方法ではありませんが、動作するようです (html5 をサポートするブラウザーで)。誰かが改善のための提案を持っている場合は、私に知らせてください。maxSliceSize を動かして動作させる必要がありましたが、取得できる最大値は 256 * 32 でした。
おかげで:
http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/
javascriptのみを使用して画像をバイト配列に変換し、SQLサーバーに画像を保存する方法は?
http://www.west-wind.com/weblog/posts/2009/Sep/15/Making-jQuery-calls-to-WCFASMX-with-a-ServiceProxy-Client
コードは次のとおりです (私のプロジェクトにのみ関連するコードの一部を切り取ったので、残っているものが意味をなすことを願っています):
var reader;
var filename;
var sContainer;
var maxSliceSize = 256 * 32;
var selectedFile = null;
var sliceIds = new Array();
var upFile;
function handleFileUpload(cnt, sType) {
var files = cnt.files; // FileList object
selectedFile = files[0];
//----------------------------CHECKS---------------------------
//Check whether there is a file to upload
if (files.length === 0) { return; }
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
return;
}
//test whether this is an image file
rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;
if (!rFilter.test(selectedFile.type)) { alert("You must select a valid image file!"); return; }
//----------------------------UPLOAD---------------------------
//Create a name for the blob
filename = selectedFile.name.toLowerCase();
sContainer = "images"
//Upload the file
reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
//Initialise variables
maxSliceSize = 256 * 32;
upFile = evt.target.result
sliceIds = new Array();
uploadFileInSlices();
}
}
reader.readAsDataURL(selectedFile);
}
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
function uploadFileInSlices() {
if (upFile != "") {
var sliceId = pad(sliceIds.length, 6);
console.log("slice id = " + sliceId);
sliceIds.push(sliceId);
//Send the first slice off to the server and remove it from the file string
var upSlice = upFile.substring(0, maxSliceSize);
upFile = upFile.substring(maxSliceSize);
var params = {
filename: filename,
sliceID: sliceId,
upSlice: upSlice
};
proxy.invoke("UploadImageSlice", params, uploadFileInSlices, onProxyFailure, true);
} else {
commitSliceList();
}
}
function commitSliceList() {
var jsonData = []; //declare object
for (var i = 0; i < sliceIds.length; i++) {
jsonData.push({ SliceName: sliceIds[i] });
}
console.log(jsonData);
var params = {
filename: filename,
sliceList: jsonData,
upFileType: selectedFile.type,
sContainer: sContainer
};
proxy.invoke("UploadImage", params, onSuccess, onProxyFailure, true);
}
Web サービス (これらは完全ではありませんが、基本的なアイデアを提供する必要があります):
<OperationContract()>
Public Function UploadImageSlice(ByVal blobFileName As String, ByVal sliceID As String, ByVal upSlice As String, iInspection As Integer) As Boolean
HttpContext.Current.Session(blobFileName & sliceID) = upSlice
Return true
End Function
<OperationContract()>
Public Function UploadImage(ByVal blobFileName As String,ByVal sliceList As List(Of SliceList), upFileType As String, ByVal sContainer As String) As Boolean
'Find the root path for local storage
Dim sRoot As String = ""
Dim myReportsStorage As LocalResource = RoleEnvironment.GetLocalResource("myReports")
sRoot = myReportsStorage.RootPath
'Check whether the file already exists in local storage
If My.Computer.FileSystem.FileExists(sRoot & blobFileName) Then
My.Computer.FileSystem.DeleteFile(sRoot & blobFileName)
End If
‘GlueUploadSlices pulls strings out of session variables and sticks them together
Dim upFile As String = GlueUploadSlices(blobFileName, sliceList)
Dim upFileByte As [Byte]() = New [Byte](upFile.Length - 1) {}
'FixBase64ForImage extracts the appropriate string from upFile
upFileByte = Convert.FromBase64String(FixBase64ForImage(upFile))
Using fs As FileStream = File.OpenWrite(sRoot & blobFileName)
fs.Write(upFileByte, 0, upFileByte.Length)
fs.Close()
End Using
'Save file to local storage
StoreBlob(sContainer, sRoot, blobFileName)
Return true
End Function