Comment télécharger d'énormes fichiers vers le blob Azure à partir d'une page web
interne ASP.NET dispose d'un espace d'adressage de 2 Go, mais en réalité vous n'avez que moins de 1 Go libre pour les téléchargements (voir http://support.microsoft.com/?id=295626 ). En outre, IIS 7 a un plafond de 30 MB ( voir ). http://www.iislogs.com/steveschofield/iis7-post-40-adjusting-file-upload-size-in-iis7 ) et vous auriez à courir
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 cette sur mes serveurs Azure?
aussi, selon http://support.microsoft.com/?id=295626
pendant le processus de téléchargement, ASP.NET charge tout le fichier en mémoire avant l'utilisateur peut sauvegarder le fichier disque.
, donc je vais rapidement épuiser la limite de mémoire si de nombreux utilisateurs téléchargent de gros fichiers à la fois. Dans mon code ci-dessous, j'utilise les flux, mais je devine que l'ensemble le fichier est d'abord téléchargé en mémoire. 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 au courant d'outils non de téléchargement de page web comme http://azureblobuploader.codeplex.com / , mais j'ai vraiment besoin qu'il soit téléchargé à partir d'une page web.
donc, mes questions sont:
- Comment puis-je télécharger des fichiers sur le blob qui sont plus de 2 GO à partir d'une page web
- Comment puis-je télécharger de grands fichiers à partir une page web comme un flux qui ne mange pas toute la mémoire
- si la solution est d'écrire mon propre HttpModule ou HttpHandler pour gérer mon téléchargement, Comment puis-je l'installer sur mes serveurs Azure? Puis-je utiliser des HttpHandlers comme http://neatupload.codeplex.com / on Azure?
- ce projet n'est pas sur SharePoint, mais je sais que dans SharePoint vous avez quelque chose appelé un fournisseur Blob et que vous pouvez écrire votre propre, sont-il Blob Fournisseurs de ASP.NET je ne sais pas.
je peux également mentionner que mon code ci-dessus fonctionne très bien par défaut avec des fichiers inférieurs à 30 Mo, J'utilise SWFUpload V2.2.0 sur le client.
mise à jour 19. 19 Juin: 09: @YvesGoeleven sur Twitter m'a donné un conseil d'utiliser la Signature D'accès partagé (voir msdn.microsoft.com/en-us/library/ee395415.aspx ) et le téléchargement du fichier directement dans le stockage Blob Azure sans passer par le ASP.NET pas du tout. J'ai créé un JSON WCF qui retourne un sasut valide à mon stockage 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);
}
}
}
cela fonctionne, mais je ne peux pas l'utiliser avec SWFUpload car il utilise le verbe HTTP POST et non le verbe HTTP PUT que le stockage Blob Azure attend lors de la création d'un nouvel élément blob. Quelqu'un sait comment contourner cela sans faire mon propre Silverlight personnalisé ou composant client Flash qui utilise le verbe HTTP PUT? Je voulais une barre de progression lors du téléchargement des fichiers, donc un formulaire soumis qui les usages mis ne sont pas optimaux.
pour ceux qui sont intéressés par le code client (qui ne fonctionnera pas puisque SWFUpload utilise HTTP POST et non pas mis 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. 21 juin: 07:
j'ai pensé depuis SWFUpload est open source que je télécharge la source et changer le Verbe de la poste à mettre, malheureusement le lecteur Flash URLRequestMethod ne supporte pas d'autres verbes que GET et POST. J'ai trouvé une supposée de travail 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 ne fonctionne Qu'avec Adobe Air et pas avec Flash Player.
J'ai lu que SilverLight 3 et plus tard supporte le verbe HTTP PUT, donc je pense que je dois écrire un code SilverLight pour obtenir mon chemin ici. J'ai bien trouvé cette série d'articles de blog 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 grands fichiers (testés avec des fichiers de 4,5 Go) à partir d'une page Web en utilisant un client Silverlight personnalisé que 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 à la fois le verbe mis HTTP que Azure Blob Storage nécessite et prend en charge les téléchargements progressifs, j'ai maintenant la possibilité de télécharger des fichiers massifs directement dans le stockage Blob Azure et je n'ai pas à aller ASP.NET solution, j'obtiens aussi de belles barres de progression et l'utilisateur peut annuler au milieu du téléchargement s'il/elle le souhaite. 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 fourni à partir d'un service RESTfull WCF sur demande. Je pense que cette solution est la meilleure que nous ayons trouvé. Grâce.
mise à Jour @ 18. Juillet '11:
j'ai créé un projet open source avec ce que j'ai trouvé ici:
4 réponses
peu importe le code que vous utilisez. Si vous écrivez un code côté serveur, alors le fichier va aller à votre webrole et puis plusieurs douleurs telles que le recyclage de rôle et le retour des téléchargements défectueux va venir. J'ai retiré ces problèmes par un contrôle Silverlight côté client, qui non seulement a fait des chargements tolérant les défauts, mais aussi l'a fait à une grande vitesse. Vous pouvez télécharger mon échantillon et lire comment je l'ai construit à partir de: choisissez votre contrôle de téléchargement de fichier Azure: Silverlight et TPL ou HTML5 et AJAX
nous pouvons télécharger de très gros fichiers dans le stockage azure en utilisant le téléchargement parallèle. Cela signifie que nous devons diviser les gros fichiers en morceaux de petits paquets de fichiers et et uoploaded ces paquets. Une fois le téléchargement terminé, nous pouvons rejoindre les paquets de un exemplaire original. Pour le code complet, reportez-vous au lien suivant http://tuvian.wordpress.com/2011/06/28/how-to-upload-large-size-fileblob-to-azure-storage-using-asp-netc/
pour cette partie de la question:
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 lancer ceci sur mes serveurs Azure?
vous pouvez faire cela en utilisant les tâches de démarrage - voir http://richardprodger.wordpress.com/2011/03/22/azure-iis7-configuration-with-appcmd /