Skip to content

Instantly share code, notes, and snippets.

@tugberkugurlu
Created September 4, 2012 14:30
Show Gist options
  • Save tugberkugurlu/3621671 to your computer and use it in GitHub Desktop.
Save tugberkugurlu/3621671 to your computer and use it in GitHub Desktop.
Windows Azure Storage large file upload service
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace AzureStorageUpload.Services {
public class UploadService : IUploadService {
private readonly IApplicationSettings _appSettings;
private const int MaxBlockSize = 512000; // 515KB chunk size
public UploadService(IApplicationSettings appSettings) {
_appSettings = appSettings;
}
public async Task Upload(Stream inputStream, string containerReferenceName, string blobReferenceName) {
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_appSettings.StorageConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerReferenceName);
if (await container.CreateIfNotExistAsync()) {
await container.SetPermissionsAsync(
new BlobContainerPermissions {
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
CloudBlockBlob blob = container.GetBlockBlobReference(blobReferenceName);
if (inputStream.Length > MaxBlockSize) {
HashSet<string> blocklist = new HashSet<string>();
IEnumerable<FileBlock> fileBlocks = GetFileBlocks(ReadFully(inputStream));
foreach (FileBlock block in fileBlocks)
using(var tempStream = new MemoryStream(block.Content, true)) {
await blob.PutBlockAsync(block.Id, tempStream, null);
blocklist.Add(block.Id);
}
await blob.PutBlockListAsync(blocklist);
}
else {
await blob.UploadFromStreamAsync(inputStream);
}
}
private IEnumerable<FileBlock> GetFileBlocks(byte[] fileContent) {
HashSet<FileBlock> fileBlockSet = new HashSet<FileBlock>();
if (fileContent.Length == 0) {
return new HashSet<FileBlock>();
}
int blockId = 0;
int ix = 0;
int currentBlockSize = MaxBlockSize;
while (currentBlockSize == MaxBlockSize) {
if ((ix + currentBlockSize) > fileContent.Length) {
currentBlockSize = fileContent.Length - ix;
}
byte[] chunk = new byte[currentBlockSize];
Array.Copy(fileContent, ix, chunk, 0, currentBlockSize);
fileBlockSet.Add(
new FileBlock() {
Content = chunk,
Id = Convert.ToBase64String(System.BitConverter.GetBytes(blockId))
});
ix += currentBlockSize;
blockId++;
}
return fileBlockSet;
}
private static byte[] ReadFully(Stream stream) {
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream()) {
while (true) {
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}
private class FileBlock {
public string Id { get; set; }
public byte[] Content { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment