wake-up-neo.com

Umbenennen von Azure Storage Blob

Kann ein Azure Storage Blob mithilfe der Azure Storage API von einer Webrolle aus umbenannt werden? Die einzige Lösung, die ich momentan habe, ist, den Blob in einen neuen Blob mit dem richtigen Namen zu kopieren und den alten zu löschen.

40
Geoff

Es gibt einen praktischen Weg dazu , obwohl Azure Blob Service API die Fähigkeit zum Umbenennen oder Verschieben von Blobs nicht direkt unterstützt.

28
Rinat Abdullin

AKTUALISIEREN:

Ich habe den Code nach den Kommentaren von @IsaacAbrahams und der Antwort von @ Viggity aktualisiert. Diese Version sollte verhindern, dass Sie alles in einen MemoryStream laden müssen, und wartet, bis der Kopiervorgang abgeschlossen ist, bevor Sie den Quell-Blob löschen.


Für alle, die sich verspätet auf die Party begeben, aber mit Azure Storage API V2 über diesen Beitrag stolpern, finden Sie hier eine Erweiterungsmethode , Um es schnell und schmutzig zu machen (+ async-Version):

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 Exception("Rename failed: " + target.CopyState.Status);

      await source.DeleteAsync();
    }
}

Update für 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 Exception("Rename failed: " + target.CopyState.Status);

        await source.DeleteAsync();            
    }

Haftungsausschluss: Dies ist eine schnelle und fehlerhafte Methode, um die Umbenennung synchron auszuführen. Es passt zu meinen Zwecken. Wie andere Benutzer bereits sagten, kann das Kopieren jedoch sehr lange dauern (bis zu einigen Tagen). Daher ist es am besten, diese Methode NICHT in einer Methode wie dieser Antwort auszuführen, sondern stattdessen:

  • Starten Sie den Kopiervorgang
  • Den Status des Kopiervorgangs abfragen
  • Löschen Sie den ursprünglichen Fleck, wenn die Kopie abgeschlossen ist. 
38
Wiebe Tijsma

Sie können jedoch kopieren und dann löschen.

26
smarx

Ich habe ursprünglich Code von @Zidad verwendet, und unter niedrigen Lastbedingungen hat es normalerweise funktioniert (ich benenne fast immer kleine Dateien um, ~ 10kb). 

NICHT StartCopyFromBlob dann Delete !!!!!!!!!!!!!!

In einem Szenario mit hoher Auslastung hat I LOST ~ 20% der Dateien, die ich umbenannt habe (Tausende von Dateien) . Wie in den Kommentaren zu seiner Antwort erwähnt, startet StartCopyFromBlob einfach die Kopie. Es gibt keine Möglichkeit für Sie zu warten, bis die Kopie fertig ist.  

Sie können nur garantieren, dass die Kopie fertig ist, indem Sie sie herunterladen und erneut hochladen. Hier ist mein aktualisierter Code: 

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

Während dies ein alter Beitrag ist, wird dieser ausgezeichneter Blogbeitrag vielleicht anderen zeigen, wie Blobs, die hochgeladen wurden, sehr schnell umbenannt werden können.

Hier sind die Highlights:

//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();
12
paqogomez

Kopieren Sie den Blob und löschen Sie ihn.

Getestet für Dateien der Größe 1G, und es funktioniert OK. 

Weitere Informationen finden Sie im sample in 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();  
    } 
} 
5
Ann Yu

Dies funktionierte für mich in einer Live-Umgebung von 100.000 Benutzern mit einer Dateigröße von nicht mehr als 100 MB. Dies ist ein ähnlicher synchroner Ansatz wie bei der Antwort von @viggity. Der Unterschied ist jedoch, dass alles auf Azure-Seite kopiert wird, sodass Sie Memorystream nicht auf Ihrem Server speichern müssen, um in neuen Blob kopieren/hochladen zu können. 

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

Wenn Sie die ContentDisposition-Eigenschaft mit festlegen

attachment;filename="yourfile.txt"

Der Name des Downloads über http ist beliebig.

Ich denke, Storage wurde mit der Annahme erstellt, dass Daten auf eine Art und Weise gespeichert werden, bei der eindeutige Bezeichner in erster Linie als Dateinamen verwendet werden. Das Ausgeben von Shared Access-Signaturen für alle Downloads ist allerdings etwas seltsam, weshalb dies für manche Menschen nicht ideal ist.

Ich halte es jedoch für eine gute Praxis, den benutzerbezogenen Dateinamen zu entfernen, und ermutige insgesamt zu einer stabileren Architektur.

0
Bon

Momentan ist die einzige Möglichkeit, den src-Blob an ein neues Ziel/einen neuen Namen zu verschieben. Hier ist mein Code, um dies zu tun

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

Hier ein Codebeispiel, wenn Sie die Blob-Suche als Teil der Methode wünschen:

    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;
    }
0
Darrelk

Sie können jetzt mit der neuen Version in der öffentlichen Vorschau von ADLS Gen 2 ( Azure Data Lake Storage Gen 2 )

Mit der Funktion Hierarchical Namespace können Sie Verzeichnisse und Dateien atomar bearbeiten, einschließlich der Operation Rename .

Beachten Sie jedoch Folgendes: "Wenn Sie mit dem Preview-Release den hierarchischen Namespace aktivieren, besteht keine Interoperabilität der Daten oder Operationen zwischen Blob und Data Lake Storage Gen2 REST-APIs. Diese Funktionalität wird während der Vorschau hinzugefügt. "

Sie müssen sicherstellen, dass Sie die Blobs (Dateien) mit ADLS Gen 2 erstellen, um sie umzubenennen. Warten Sie andernfalls, bis die Interoperabilität zwischen Blob-APIs und ADLS Gen 2 während des Vorschauzeitraums hinzugefügt wird.

0
Saher Ahwal