Внутренне ASP.NET имеет адресное пространство 2 ГБ, но на самом деле у вас меньше 1 ГБ свободного места для загрузки (см. http: / /support.microsoft.com/?id=295626 ). Вдобавок IIS 7 имеет ограничение в 30 МБ (см. 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
на сервере, чтобы выйти за пределы 30 МБ. Но как я могу запустить это на моих серверах Azure?
Кроме того, согласно http://support.microsoft.com/?id=295626
В процессе загрузки ASP.NET загружает весь файл в память перед пользователь может сохранить файл в disk.
, поэтому я быстро исчерпаю лимит памяти, если многие пользователи загружают большие файлы одновременно. В моем коде ниже я использую потоки, но я предполагаю, что в любом случае весь файл сначала загружается в память. Так ли это?
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/ , но мне действительно нужно, чтобы они загружались с веб-страницы.
Итак, мои вопросы:
Я также могу упомянуть, что приведенный выше код отлично работает по умолчанию с файлами размером менее 30 МБ, я использую SWFUpload V2.2.0 на клиенте.
Обновление 19. июня 19:09: @YvesGoeleven в Твиттере дал мне совет по использованию подписи общего доступа (см. Msdn.microsoft.com/en-us/library/ee395415.aspx) и загрузки файла непосредственно в хранилище BLOB-объектов Azure без использования ASP.NET. . Я создал JSON WCF, который возвращает действительный SAS ut в мое хранилище BLOB-объектов.
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);
}
}
}
Он работает, но я не могу использовать его с SWFUpload, поскольку он использует команду HTTP POST, а не команду HTTP PUT, которую хранилище BLOB-объектов Azure ожидает при создании нового элемента BLOB-объектов. Кто-нибудь знает, как обойти это, не создавая собственный клиентский компонент Silverlight или Flash, который использует команду HTTP PUT? Мне нужен индикатор выполнения при загрузке файлов, поэтому отправленная форма, использующая PUT, не оптимальна.
Для тех, кто интересуется клиентским кодом (который не будет работать, поскольку SWFUpload использует HTTP POST, а не PUT, как ожидает хранилище BLOB-объектов Azure):
SWFUpload
v2.2.0
Application Demo (ASP.Net 2.0)
Обновление 19 июня, 21:07:
Я понял, поскольку SWFUpload является открытым исходным кодом что я загружаю исходный код и меняю команду с POST на PUT, к сожалению, Flash Player URLRequestMethod не поддерживает другие команды, кроме 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, а не с Flash Player.
Я читал, что SilverLight 3 и более поздние версии поддерживают команду HTTP PUT, поэтому я думаю, что мне нужно напишите немного кода SilverLight, чтобы добраться сюда. Я нашел эту серию статей в блоге, которые, вероятно, помогут мне здесь http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures .
Обновление от 27. июня 2011 г .:
Теперь мне удалось успешно загрузить большие файлы (проверено с файлами размером 4,5 ГБ) с веб-страницы с помощью специального клиента Silverlight, который я написал на основе проекта. в http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures . Поскольку Silverlight поддерживает как команду HTTP PUT, которую требует хранилище BLOB-объектов Azure, так и прогрессивную загрузку, теперь у меня есть возможность выгружать большие файлы непосредственно в хранилище BLOB-объектов Azure, и мне не нужно использовать решение ASP.NET, я также Получите несколько хороших индикаторов выполнения, и пользователь может отменить в середине загрузки, если он / она хочет. Использование памяти на сервере минимально, поскольку весь файл не выгружается до того, как он будет помещен в хранилище BLOB-объектов Azure. Я использую подпись общего доступа (см. Msdn.microsoft.com/en-us/library/ee395415.aspx), которая предоставляется службой WCF RESTfull по запросу. Я думаю, что это лучшее решение, которое мы нашли. Спасибо.
Обновление @ 18 июля '11:
Я создал проект с открытым исходным кодом, используя то, что я нашел здесь: