Можно ли переименовать Azure Storage Blob с использованием Azure Storage API из веб-роли? Единственное решение, которое у меня есть на данный момент, - скопировать blob в новый blob с правильным именем и удалить старый.
Azure Storage Blob Переименовать
Ответ 1
В настоящее время невозможно переименовать blob за одну операцию.
Azure API службы Blob не поддерживает возможность переименовывать или перемещать капли.
Ответ 2
UPDATE:
Я обновил код после комментариев @IsaacAbrahams и ответа @Viggity, эта версия должна помешать вам загружать все в MemoryStream и ждет, пока копия не будет завершена до удаления исходного блоба.
Для тех, кто опаздывает на вечеринку, но наткнулся на это сообщение, используя Azure Storage API V2, здесь метод расширения для быстрого и грязного (+ асинхронная версия):
public static class BlobContainerExtensions
{
public static void Rename(this CloudBlobContainer container, string oldName, string newName)
{
//Warning: this Wait() is bad practice and can cause deadlock issues when used from ASP.NET applications
RenameAsync(container, oldName, newName).Wait();
}
public static async Task RenameAsync(this CloudBlobContainer container, string oldName, string newName)
{
var source = await container.GetBlobReferenceFromServerAsync(oldName);
var target = container.GetBlockBlobReference(newName);
await target.StartCopyFromBlobAsync(source.Uri);
while (target.CopyState.Status == CopyStatus.Pending)
await Task.Delay(100);
if (target.CopyState.Status != CopyStatus.Success)
throw new ApplicationException("Rename failed: " + target.CopyState.Status);
await source.DeleteAsync();
}
}
Обновление для Azure Storage 7.0
public static async Task RenameAsync(this CloudBlobContainer container, string oldName, string newName)
{
CloudBlockBlob source =(CloudBlockBlob)await container.GetBlobReferenceFromServerAsync(oldName);
CloudBlockBlob target = container.GetBlockBlobReference(newName);
await target.StartCopyAsync(source);
while (target.CopyState.Status == CopyStatus.Pending)
await Task.Delay(100);
if (target.CopyState.Status != CopyStatus.Success)
throw new ApplicationException("Rename failed: " + target.CopyState.Status);
await source.DeleteAsync();
}
Отказ от ответственности: это быстрый и грязный метод, позволяющий выполнять переименование синхронно. Это соответствует моим целям, однако, как отмечали другие пользователи, копирование может занять много времени (до нескольких дней), поэтому наилучшим способом НЕ является выполнение этого в 1 методе, таком как этот ответ, но вместо этого:
- Запустить процесс копирования
- Опросить состояние операции копирования
- Удалить копию оригинала, когда копия завершена.
Ответ 3
Вы можете, однако, скопировать и удалить.
Ответ 4
Я изначально использовал код из @Zidad, и в условиях низкой нагрузки он обычно работал (я почти всегда переименовываю небольшие файлы, ~ 10kb).
НЕ StartCopyFromBlob
, затем Delete
!!!!!!!!!!!!!!
В сценарии с высокой нагрузкой я LOST ~ 20% файлов, которые я переименовал (тысячи файлов). Как упоминалось в комментариях к его ответу, StartCopyFromBlob
только начинает копировать. Невозможно дождаться завершения копирования.
Единственный способ гарантировать завершение копирования - загрузить и повторно загрузить. Вот мой обновленный код:
public void Rename(string containerName, string oldFilename, string newFilename)
{
var oldBlob = GetBlobReference(containerName, oldFilename);
var newBlob = GetBlobReference(containerName, newFilename);
using (var stream = new MemoryStream())
{
oldBlob.DownloadToStream(stream);
stream.Seek(0, SeekOrigin.Begin);
newBlob.UploadFromStream(stream);
//copy metadata here if you need it too
oldBlob.Delete();
}
}
Ответ 5
Хотя это старый пост, возможно, этот отличный пост в блоге покажет другим, как очень быстро переименовать капли, которые были загружены.
Вот основные моменты:
//set the azure container
string blobContainer = "myContainer";
//azure connection string
string dataCenterSettingKey = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", "xxxx",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
//setup the container object
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(dataCenterSettingKey);
CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(blobContainer);
// Set permissions on the container.
BlobContainerPermissions permissions = new BlobContainerPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(permissions);
//grab the blob
CloudBlob existBlob = container.GetBlobReference("myBlobName");
CloudBlob newBlob = container.GetBlobReference("myNewBlobName");
//create a new blob
newBlob.CopyFromBlob(existBlob);
//delete the old
existBlob.Delete();
Ответ 6
Скопируйте blob и удалите его.
Протестировано для файлов размером 1G, и оно работает нормально.
Для получения дополнительной информации см. образец в MSDN.
StorageCredentials cred = new StorageCredentials("[Your?storage?account?name]", "[Your?storage?account?key]");
CloudBlobContainer container = new CloudBlobContainer(new Uri("http://[Your?storage?account?name].blob.core.windows.net/[Your container name] /"), cred);
string fileName = "OldFileName";
string newFileName = "NewFileName";
await container.CreateIfNotExistsAsync();
CloudBlockBlob blobCopy = container.GetBlockBlobReference(newFileName);
if (!await blobCopy.ExistsAsync())
{
CloudBlockBlob blob = container.GetBlockBlobReference(fileName);
if (await blob.ExistsAsync())
{
// copy
await blobCopy.StartCopyAsync(blob);
// then delete
await blob.DeleteIfExistsAsync();
}
}
Ответ 7
Это работало для меня в живой среде пользователей 100K, имеющих размер файлов не более 100 мб. Это аналогичный синхронный подход к ответу @viggity. Но разница в том, что он копирует все на стороне Azure, поэтому вам не нужно хранить Memorystream на своем сервере для копирования/загрузки в новый Blob.
var account = new CloudStorageAccount(new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(StorageAccountName, StorageAccountKey), true);
CloudBlobClient blobStorage = account.CreateCloudBlobClient();
CloudBlobContainer container = blobStorage.GetContainerReference("myBlobContainer");
string fileName = "OldFileName";
string newFileName = "NewFileName";
CloudBlockBlob oldBlob = container.GetBlockBlobReference(fileName);
CloudBlockBlob newBlob = container.GetBlockBlobReference(newFileName);
using (var stream = new MemoryStream())
{
newBlob.StartCopyFromBlob(oldBlob);
do { } while (!newBlob.Exists());
oldBlob.Delete();
}
Ответ 8
Единственный способ - переместить sbc blob в новый пункт назначения/имени. Вот мой код, чтобы сделать это
public async Task<CloudBlockBlob> RenameAsync(CloudBlockBlob srcBlob, CloudBlobContainer destContainer,string name)
{
CloudBlockBlob destBlob;
if (srcBlob == null && srcBlob.Exists())
{
throw new Exception("Source blob cannot be null and should exist.");
}
if (!destContainer.Exists())
{
throw new Exception("Destination container does not exist.");
}
//Copy source blob to destination container
destBlob = destContainer.GetBlockBlobReference(name);
await destBlob.StartCopyAsync(srcBlob);
//remove source blob after copy is done.
srcBlob.Delete();
return destBlob;
}
Вот пример кода, если вы хотите, чтобы запрос blob был частью метода:
public CloudBlockBlob RenameBlob(string oldName, string newName, CloudBlobContainer container)
{
if (!container.Exists())
{
throw new Exception("Destination container does not exist.");
}
//Get blob reference
CloudBlockBlob sourceBlob = container.GetBlockBlobReference(oldName);
if (sourceBlob == null && sourceBlob.Exists())
{
throw new Exception("Source blob cannot be null and should exist.");
}
// Get blob reference to which the new blob must be copied
CloudBlockBlob destBlob = container.GetBlockBlobReference(newName);
destBlob.StartCopyAsync(sourceBlob);
//Delete source blob
sourceBlob.Delete();
return destBlob;
}