Comment télécharger de gros fichiers à l'Azure blob à partir d'une page web

En interne ASP.NET a un 2 GO d'espace d'adressage, mais en réalité, vous avez pas plus de 1 GO gratuit pour les téléchargements (voir http://support.microsoft.com/?id=295626 ). En outre IIS 7 a un plafond de 30 MO ( voir http://www.iislogs.com/steveschofield/iis7-post-40-adjusting-file-upload-size-in-iis7 ) et vous avez soi-disant pour exécuter

appcmd set config "My Site/MyApp" -section:requestFiltering -requestLimits.maxAllowedContentLength:104857600 -commitpath:apphost

sur le serveur pour aller au-delà de cette limite de 30 MO. Mais comment puis-je exécuter sur mes serveurs Azure?

Aussi, selon http://support.microsoft.com/?id=295626

Pendant le processus de téléchargement, ASP.NET
les charges de l'ensemble du fichier en mémoire avant
l'utilisateur peut enregistrer le fichier à l'
de disque.

donc je vais épuiser rapidement la limite de la mémoire si de nombreux utilisateurs de télécharger de gros fichiers à la fois. Dans mon code ci-dessous j'ai utiliser les flux, mais je devine que tout le fichier est téléchargé dans la mémoire de toute façon. Est-ce le cas?

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();
}
}
}
}

Je suis conscient de la non page web de téléchargement des outils comme http://azureblobuploader.codeplex.com/ , mais j'ai vraiment besoin d'être téléchargés à partir d'une page web.

Donc, mes questions sont les suivantes:

  1. Comment puis-je télécharger des fichiers sur le blob qui sont plus de 2 GO à partir d'une page web
  2. Comment puis-je grand de télécharger des fichiers à partir d'une page web comme un flux qui ne mangent pas tous la mémoire
  3. Si la solution est d'écrire ma propre HttpModule ou HttpHandler pour gérer mon upload, comment puis-je obtenir de l'installer sur mon Azure serveurs? Puis-je utiliser HttpHandlers comme http://neatupload.codeplex.com/ sur Azure?
  4. Ce projet n'est pas sur SharePoint, mais je sait que dans SharePoint vous avez quelque chose qui s'appelle une Goutte Fournisseur et que vous pouvez écrire votre propre, il y a Blob Fournisseurs pour ASP.NET?

Je peux aussi mentionner que mon code ci-dessus fonctionne très bien par défaut avec des fichiers de moins de 30 MO, j'utilise SWFUpload V2.2.0 sur le client.

Mise à jour 19. Juin 19:09:
@YvesGoeleven sur Twitter m'a donné une astuce de l'utilisation de la Signature d'Accès Partagé (voir msdn.microsoft.com/en-us/library/ee395415.aspx ) et d'envoyer le fichier directement à l'Azure Blob Storage, sans passer par le ASP.NET à tous. J'ai créé un JSON WCF qui renvoie valide SAS ut à mon blob storage.

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);
}
}
}

Il fonctionne, mais je ne peux pas l'utiliser avec SWFUpload car il utilise le HTTP verbe POST et de ne pas le METTRE HTTP verbe que l'Azure Blob Storage attend lors de la création d'un nouveau blob élément. Quelqu'un sait comment contourner ce problème sans faire mon propre Silverlight ou Flash composant client qui utilise le HTTP PUT verbe? Je voulais une barre de progression lors du téléchargement de fichiers, donc de la soumission d'un formulaire qui utilise n'est pas optimale.

Pour ceux qui sont intéressés dans le code du client (qui ne fonctionnent pas depuis SWFUpload utilise HTTP POST et ne pas METTRE comme Azure Blob Storage attend):

    <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>

Mise à jour 19. Juin 21:07:

J'ai trouvé depuis SWFUpload est open source que j'ai télécharger la source et changer le verbe de POST pour METTRE, malheureusement, le Flash Player URLRequestMethod ne prend pas en charge d'autres verbes que GET et POST. J'ai trouvé un supposé travailler autour de

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"));

mais cela n'a de travail dans Adobe Air et pas avec le Flash Player.

J'ai lu que SilverLight 3 et versions ultérieures prennent en charge le HTTP PUT verbe, donc je pense que je dois écrire quelques SilverLight code pour obtenir mon chemin. J'ai trouvé cet article de blog de la série qui va probablement m'aider ici http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures .

Mise à jour @ 27. Juin '11:

J'ai maintenant réussi à télécharger de gros fichiers (testé avec 4,5 Go de fichiers) à partir d'une page web à l'aide d'un custom client Silverlight, j'ai écrit basé sur le projet dans http://blog.smarx.com/posts/uploading-windows-azure-blobs-from-silverlight-part-1-shared-access-signatures . Depuis Silverlight prend en charge le HTTP PUT verbe qui Azure Blob Storage nécessite et prend en charge progressive téléchargements, j'ai maintenant la possibilité de télécharger massive des fichiers directement à l'Azure Blob Storage et je n'ai pas à aller throgh un ASP.NET la solution, je reçois aussi quelques belles barres de progression, et l'utilisateur peut annuler dans le milieu de la télécharger si il/elle veut. L'utilisation de la mémoire sur le serveur est minime puisque le fichier n'est pas téléchargé, avant d'être placé dans l'Azure Blob Storage. J'utilise une Signature d'Accès Partagé (voir msdn.microsoft.com/en-us/library/ee395415.aspx ) qui est alimenté à partir d'un WCF de Détente sur demande. Je pense que cette solution est la meilleure que nous ayons trouvé. Merci.

Mise à jour @ 18. Juillet '11:

J'ai créé un projet open source avec ce que j'ai trouvé ici:

http://azureslfileuploader.codeplex.com/

OriginalL'auteur | 2011-06-19