内部的には、ASP.NETには2 GBのアドレス空間がありますが、実際には、アップロードに使用できる空き容量は1 GB未満です(http://support.microsoft.com/?id=295626を参照)。さらに、IIS7の上限は30MBであり(http://www.iislogs.com/steveschofield/iis7-post-40-adjusting-file-upload-size-in-iis7を参照)、おそらく実行する必要があります。
appcmd set config "My Site/MyApp" -section:requestFiltering -requestLimits.maxAllowedContentLength:104857600 -commitpath:apphost
サーバー上でこの30MBの制限を超えます。しかし、Azureサーバーでこれを実行するにはどうすればよいですか?
また、http://support.microsoft.com/?id=295626によると
アップロードプロセス中に、ASP.NETは、ユーザーがファイルをディスクに保存する前に、ファイル全体をメモリにロードします。
、したがって、多くのユーザーが一度に大きなファイルをアップロードすると、メモリ制限をすぐに使い果たしてしまいます。以下のコードではストリームを使用していますが、とにかくファイル全体が最初にメモリにアップロードされると思います。これは本当ですか?
using System;
using System.Web.Security;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
namespace WebPages
{
public partial class Upload : System.Web.UI.Page
{
CloudBlobClient BlobClient = null;
CloudBlobContainer BlobContainer = null;
void InitBlob()
{
// Setup the connection to Windows Azure Storage
var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
BlobClient = storageAccount.CreateCloudBlobClient();
// Get and create the container
BlobContainer = BlobClient.GetContainerReference("publicfiles");
}
protected void Page_Load(object sender, EventArgs e)
{
//if (Membership.GetUser() == null) return; // Only allow registered users to upload files
InitBlob();
try
{
var file = Request.Files["Filedata"];
var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
BlobClient = storageAccount.CreateCloudBlobClient();
// Make a unique blob name
var extension = System.IO.Path.GetExtension(file.FileName);
// Create the Blob and upload the file
var blobAddressUri = String.Format("{0}{1}", Guid.NewGuid(), extension);
var blob = BlobContainer.GetBlobReference(blobAddressUri);
blob.UploadFromStream(file.InputStream);
// Set the metadata into the blob
blob.Metadata["FileName"] = file.FileName;
//blob.Metadata["Submitter"] = Membership.GetUser().UserName;
blob.Metadata["Type"] = "Video";
blob.Metadata["Description"] = "Test";
blob.SetMetadata();
// Set the properties
blob.Properties.ContentType = file.ContentType;
blob.SetProperties();
}
catch(Exception ex)
{
System.Diagnostics.Trace.TraceError("Upload file exception: {0}", ex.ToString());
// If any kind of error occurs return a 500 Internal Server error
Response.StatusCode = 500;
Response.Write("An error occured while uploading the file");
Response.End();
}
}
}
}
http://azureblobuploader.codeplex.com/のようなWebページ以外のアップロードツールを知っていますが、実際にはWebページからアップロードする必要があります。
だから、私の質問は次のとおりです。
- Webページから2GBを超えるファイルをblobにアップロードする方法
- すべてのメモリを消費しないストリームとしてWebページからファイルを大きくアップロードするにはどうすればよいですか?
- 解決策がアップロードを処理するために独自のHttpModuleまたはHttpHandlerを作成することである場合、これをAzureサーバーにインストールするにはどうすればよいですか?Azureでhttp://neatupload.codeplex.com/のようなHttpHandlerを使用できますか?
- このプロジェクトはSharePoint上にありませんが、SharePointにはBlobプロバイダーと呼ばれるものがあり、独自に作成できることを知っています。ASP.NET用のBlobプロバイダーはありますか?
上記のコードは、デフォルトで30 MB未満のファイルで正常に機能することにも言及できます。クライアントでは、SWFUploadV2.2.0を使用しています。
更新19.6月19:09: Twitterの@YvesGoelevenから、共有アクセス署名(msdn.microsoft.com/en-us/library/ee395415.aspxを参照)を使用し、ファイルをAzureBlobStorageに直接アップロードする方法を教えてもらいました。 ASP.NETをまったく通過しません。有効なSASutをblobストレージに返すJSONWCFを作成しました。
using System.ServiceModel;
using System.ServiceModel.Web;
namespace WebPages.Interfaces
{
[ServiceContract]
public interface IUpload
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
string GetUploadUrl();
}
}
--------
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.ServiceModel.Activation;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
namespace WebPages.Interfaces
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class UploadService : IUpload
{
CloudBlobClient BlobClient;
CloudBlobContainer BlobContainer;
public UploadService()
{
// Setup the connection to Windows Azure Storage
var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
BlobClient = storageAccount.CreateCloudBlobClient();
// Get and create the container
BlobContainer = BlobClient.GetContainerReference("publicfiles");
}
string JsonSerialize(string url)
{
var serializer = new DataContractJsonSerializer(url.GetType());
var memoryStream = new MemoryStream();
serializer.WriteObject(memoryStream, url);
return Encoding.Default.GetString(memoryStream.ToArray());
}
public string GetUploadUrl()
{
var sasWithIdentifier = BlobContainer.GetSharedAccessSignature(new SharedAccessPolicy()
{
Permissions = SharedAccessPermissions.Write,
SharedAccessExpiryTime =
DateTime.UtcNow.AddMinutes(60)
});
return JsonSerialize(BlobContainer.Uri.AbsoluteUri + "/" + Guid.NewGuid() + sasWithIdentifier);
}
}
}
動作しますが、新しいblobアイテムを作成するときにAzure BlobStorageが期待するHTTPPUT動詞ではなく、HTTP POST動詞を使用するため、SWFUploadでは使用できません。HTTP PUT動詞を使用する独自のカスタムSilverlightまたはFlashクライアントコンポーネントを作成せずにこれを回避する方法を知っている人はいますか?ファイルをアップロードするときにプログレスバーが必要だったため、PUTを使用して送信されたフォームは最適ではありません。
クライアントコードに関心のある方(SWFUploadはHTTP POSTを使用し、Azure Blob Storageが期待するPUTではないため機能しません):
<div id="header">
<h1 id="logo"><a href="/">SWFUpload</a></h1>
<div id="version">v2.2.0</div>
</div>
<div id="content">
<h2>Application Demo (ASP.Net 2.0)</h2>
<div id="swfu_container" style="margin: 0px 10px;">
<div>
<span id="spanButtonPlaceholder"></span>
</div>
<div id="divFileProgressContainer" style="height: 75px;"></div>
<div id="thumbnails"></div>
</div>
</div>
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$.ajax({
url: '/Interfaces/UploadService.svc/GetUploadUrl',
success: function (result) {
var parsedResult = $.parseJSON(result);
InitUploadFile(parsedResult);
}
});
function InitUploadFile(uploadUrl) {
//alert(uploadUrl);
var swfu = new SWFUpload({
// Backend Settings
upload_url: uploadUrl,
post_params: {
"ASPSESSID": "<%=Session.SessionID %>"
},
// File Upload Settings
file_size_limit: "100 MB",
file_types: "*.*",
file_types_description: "All file types",
file_upload_limit: "0", // Zero means unlimited
// Event Handler Settings - these functions as defined in Handlers.js
// The handlers are not part of SWFUpload but are part of my website and control how
// my website reacts to the SWFUpload events.
file_queue_error_handler: fileQueueError,
file_dialog_complete_handler: fileDialogComplete,
upload_progress_handler: uploadProgress,
upload_error_handler: uploadError,
upload_success_handler: uploadSuccess,
upload_complete_handler: uploadComplete,
// Button settings
button_image_url: "Images/swfupload/XPButtonNoText_160x22.png",
button_placeholder_id: "spanButtonPlaceholder",
button_width: 160,
button_height: 22,
button_text: '<span class="button">Select files <span class="buttonSmall">(2 MB Max)</span></span>',
button_text_style: '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }',
button_text_top_padding: 1,
button_text_left_padding: 5,
// Flash Settings
flash_url: "Js/swfupload-2.2.0/swfupload.swf", // Relative to this file
custom_settings: {
upload_target: "divFileProgressContainer"
},
// Debug Settings
debug: false
});
}
});
</script>
更新19.6月21:07:
SWFUploadはオープンソースであるため、ソースをダウンロードして動詞をPOSTからPUTに変更すると思いました。残念ながら、FlashPlayerURLRequestMethodはGETとPOST以外の動詞をサポートしていません。想定される回避策を見つけました
private function BuildRequest():URLRequest {
// Create the request object
var request:URLRequest = new URLRequest();
request.method = URLRequestMethod.POST;
request.requestHeaders.push(new URLRequestHeader("X-HTTP-Method-Override", "PUT"));
、ただし、これはAdobe Airでのみ機能し、FlashPlayerでは機能しません。
SilverLight3以降がHTTPPUT動詞をサポートしていることを読んだので、ここにたどり着くには、SilverLightコードを作成する必要があると思います。おそらくここhttp://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signaturesで役立つこのブログ記事シリーズを見つけました。
更新@27。2011年6月:
これで、 http://blog.smarx.com/posts/uploading-windows-のプロジェクトに基づいて作成したカスタムSilverlightクライアントを使用して、Webページから大きなファイル(4,5 Gbファイルでテスト済み)を正常にアップロードできました。azure-blobs-from-silverlight-part-1-shared-access-signatures。Silverlightは、Azure BlobStorageが必要とするHTTPPUT動詞とプログレスアップロードの両方をサポートしているため、大量のファイルをAzure Blob Storageに直接アップロードできるようになり、ASP.NETソリューションを使用する必要もありません。いくつかの素晴らしいプログレスバーを取得し、ユーザーは必要に応じてアップロードの途中でキャンセルできます。ファイル全体がAzureBlobStorageに配置される前にアップロードされないため、サーバーのメモリ使用量は最小限に抑えられます。要求に応じてWCFRESTfullサービスから提供される共有アクセス署名(msdn.microsoft.com/en-us/library/ee395415.aspxを参照)を使用します。この解決策は私たちが見つけた最高のものだと思います。ありがとう。
更新@18。2011年7月:
ここで見つけたものを使用してオープンソースプロジェクトを作成しました。