簡體   English   中英

在 Azure Blob 存儲上上傳大 Blob 時延長令牌過期時間

[英]Extend token expiration when uploading large blobs on Azure Blob Storage

我有一個 API,它為給定的 blob 名稱生成並返回 SAS 個令牌。 然后在我的前端應用程序上,我使用 API 提供的響應(憑據)以及通過瀏覽器直接選擇的文件來處理上傳。

我正在使用blockBlobClient.uploadData function。這工作正常並且上傳成功完成,但是我注意到 SAS 令牌被重新用於作為該 blob 的一部分上傳和處理的所有塊(我需要為 > 1GB 的文件做好准備), 因此,例如,如果我的服務器返回一個 5 分鍾的過期令牌,而我的用戶的連接速度很慢或部分中斷,則文件可能需要超過 5 分鍾才能完成上傳,這最終會從 Azure Blob 向瀏覽器拋出錯誤API 和文件上傳將停止。

我知道當然,一種方法是只發行壽命更長的令牌來解決這些情況,或者可能根據文件大小設置到期時間; 但我想知道是否有一種有效且不那么復雜的方式以某種方式延長令牌的過期時間(不會丟失我當前對該 blob 的上傳進度),以便即使達到第一個過期時間也可以正確上傳文件. 到目前為止還沒有在文檔中找到任何東西。

我將 NodeJs 用於我的后端 API, @azure/storage-blob npm package(我也在我的前端應用程序中使用)

希望這已經足夠清楚了。

感謝您提供的任何幫助!

解決方案 1:為持續上傳注入新的 SAS。 有時 SAS 會在大量上傳完成之前過期,對於這種情況,我們希望在上傳期間請求一個新的 SAS 令牌,而不是開始新的上傳。

嘗試使用此代碼更新 SAS 以上傳大文件。

async function upload() {
  const sasStore = new SasStore();

  const pipeline = Azure.StorageURL.newPipeline(
    new Azure.AnonymousCredential()
  );
  // Inject SAS update policy factory into current pipeline
  pipeline.factories.unshift(new SasUpdatePolicyFactory(sasStore));

  const url = "https://jsv10.blob.core.windows.net/mycontainer/myblob";
  const blockBlobURL = new Azure.BlockBlobURL(
    `${url}${await sasStore.getValidSASForBlob(url)}`, // A SAS should start with "?"
    pipeline
  );

  const file = document.getElementById("file").files[0];
  await Azure.uploadBrowserDataToBlockBlob(
    Azure.Aborter.none,
    file,
    blockBlobURL,
    {
      maxSingleShotSize: 4 * 1024 * 1024
    }
  );
}
/ azblob is default exported entry when importing Azure Storage Blob SDK by <script src="azure-storage.blob.js"></script>
// You can also import SDK by npm package with const Azure = require("@azure/storage-blob")
const Azure = azblob;

// SasStore is a class to cache SAS for blobs
class SasStore {
  constructor() {
    this.sasCache = {};
  }

  // Get a valid SAS for blob
  async getValidSASForBlob(blobURL) {
    if (
      this.sasCache[blobURL] &&
      this.isSasStillValidInNext2Mins(this.sasCache[blobURL])
    ) {
      return this.sasCache[blobURL];
    } else {
      return (this.sasCache[blobURL] = await this.getNewSasForBlob(blobURL));
    }
  }


// Return true if "se" section in SAS is still valid in next 2 mins
  isSasStillValidInNext2Mins(sas) {
    const expiryStringInSas = new URL(`http://host${sas}`).searchParams.get(
      "se"
    );
    return new Date(expiryStringInSas) - new Date() >= 2 * 60 * 1000;
  }

  // Get a new SAS for blob, we assume a SAS starts with a "?"
  async getNewSasForBlob(blobURL) {
    // TODO: You need to implement this
    return "?newSAS";
  }
}

class SasUpdatePolicyFactory {
  constructor(sasStore) {
    this.sasStore = sasStore;
  }
  create(nextPolicy, options) {
    return new SasUpdatePolicy(nextPolicy, options, this.sasStore);
  }
}

class SasUpdatePolicy extends Azure.BaseRequestPolicy {
  constructor(nextPolicy, options, sasStore) {
    super(nextPolicy, options);
    this.sasStore = sasStore;
  }

  async sendRequest(request) {
    const urlObj = new URL(request.url);
    const sas = await this.sasStore.getValidSASForBlob(
      `${urlObj.origin}${urlObj.pathname}`
    );
    new URL(`http://hostname${sas}`).searchParams.forEach((value, key) => {
      urlObj.searchParams.set(key, value);
    });

    // Update request URL with latest SAS
    request.url = urlObj.toString();

    return this._nextPolicy.sendRequest(request);
  }
}

請按照此github代碼了解更多詳細信息。要創建新的 SAS,請參閱此線程

解決方案 2:不上傳大文件,而是分上傳文件 [方法將大文件拆分成較小的文件]。 分塊上傳文件,這樣就可以上傳更大的文件,而無需在單個 go 中完全讀取它們。

更多詳細信息請參閱此文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM