سؤال

هل من الممكن إعادة تسمية Azure Storage Blob باستخدام واجهة برمجة تطبيقات Azure Storage من دور الويب؟ الحل الوحيد الذي لدي في الوقت الحالي هو نسخ النقطة إلى نقطة جديدة مع الاسم الصحيح وحذف الحذف القديم.

هل كانت مفيدة؟

المحلول

هنالك طريقة عملية للقيام بذلك, ، على الرغم من أزور API Service API لا يدعم القدرة مباشرة على إعادة تسمية أو نقل النقط.

نصائح أخرى

تحديث:

لقد قمت بتحديث الكود بعد تعليقات isaacabrahams وإجابة @Viggity ، يجب أن يمنعك هذا الإصدار من الاضطرار إلى تحميل كل شيء في MemoryStream ، وينتظر حتى يتم إكمال النسخة قبل حذف Blob Source.


لأي شخص يتأخر عن الحفلة ولكنه يتعثر في هذا المنشور باستخدام 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 Exception("Rename failed: " + target.CopyState.Status);

      await source.DeleteAsync();
    }
}

تحديث لتخزين Azure 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();            
    }

إخلاء المسئولية: هذه طريقة سريعة وقذرة لجعل إعادة تسمية تنفيذ بطريقة متزامنة. يناسب أغراضي ، ولكن كما لاحظ المستخدمون الآخرون ، فإن النسخ قد يستغرق وقتًا طويلاً (حتى أيام) ، وبالتالي فإن أفضل طريقة هي عدم أداء هذا بطريقة واحدة مثل هذه الإجابة ولكن بدلاً من ذلك:

  • ابدأ عملية النسخ
  • استطلاع حالة عملية النسخ
  • احذف النقطة الأصلية عند اكتمال النسخة.

يمكنك ، ومع ذلك ، نسخ ثم حذف.

لقد استخدمت الرمز في الأصل من Zidad ، وفي ظروف الحمل المنخفضة عادة ما تعمل (أنا دائمًا أعيد تسمية الملفات الصغيرة ، ~ 10 كيلو بايت).

لاتفعل StartCopyFromBlob ومن بعد Delete!!!!!!!!!!!!!!

في سيناريو الحمل العالي ، لقد فقدت حوالي 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();
    }
}

في حين أن هذا منشور قديم ، ربما هذا مدونة ممتازة سيظهر للآخرين كيفية إعادة تسمية النقط بسرعة تم تحميلها.

فيما يلي أبرز:

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

انسخ النقطة ، ثم احذفها.

تم اختباره لملفات بحجم 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();  
    } 
} 

لقد نجح هذا الأمر بالنسبة لي في بيئة حية تضم 100 ألف مستخدم لديهم أحجام ملفات لا يزيد عن 100 ميغابايت. هذا نهج متزامن مماثل لإجابة @Viggity. ولكن الفرق هو أن نسخ كل شيء على جانب Azure حتى لا تضطر إلى الاحتفاظ بالذاكرة على الخادم الخاص بك للنسخ/التحميل إلى New 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();
 }

الطريقة الوحيدة في MEMENT هي نقل SRC 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;
    }

يمكنك الآن مع الإصدار الجديد في المعاينة العامة لـ ADLS الجنرال 2 ( Azure Data Lake Storage Gen 2)

ال مساحة الاسم الهرمية تتيح لك القدرة على إجراء التلاعب الذري بالأدلة والملفات التي تتضمن إعادة تسمية عملية.

ومع ذلك ، لاحظ ما يلي: "مع إصدار المعاينة ، إذا قمت بتمكين مساحة الاسم الهرمية ، فلا توجد قابلية للتشغيل البيني للبيانات أو العمليات بين ALOB و Data Lake Storage Gen2 Rest. ستتم إضافة هذه الوظيفة أثناء المعاينة."

ستحتاج إلى التأكد من إنشاء blobs (الملفات) باستخدام ADLS Gen 2 لإعادة تسميتها. خلاف ذلك ، انتظر التشغيل البيني بين APIs blob و ADLS Gen 2 لإضافة خلال فترة المعاينة.

إذا قمت بتعيين خاصية ContentDisposition مع

attachment;filename="yourfile.txt"

سيكون اسم التنزيل عبر HTTP هو ما تريد.

أعتقد أن التخزين قد تم تصميمه بافتراض أن البيانات سيتم تخزينها بطريقة مع معرفات فريدة تستخدم بشكل أساسي كأسماء الملفات. يعد إصدار توقيعات الوصول المشتركة لجميع التنزيلات أمرًا غريبًا بعض الشيء ، لذلك ليس هذا مثاليًا لبعض الأشخاص.

لكنني أعتقد أن تجريد اسم الملف الذي يواجه المستخدم هو الممارسة بشكل عام ويشجع بنية أكثر استقرارًا بشكل عام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top