React Native 通过REST API Put Block Blob将大文件上传到Azure Blob存储

z31licg0  于 2023-01-18  发布在  React
关注(0)|答案(2)|浏览(139)

我正在使用React Native为Andrioid和iOS构建移动应用程序。
基于不存在支持Azure Storage API for React Native的框架的情况(所有框架都是React Native中不存在的必需浏览器),
我使用REST API与Azure存储交互,它工作得很好,例如列表容器、列表blob、获取blob和放置blob。
为了上传大文件,我尝试使用相同的mechanizm为'put block' api(如下所述:https://learn.microsoft.com/en-us/rest/api/storageservices/put-block)未成功,失败,错误代码为403。
我将感谢你的帮助。
谢谢你。
我的代码上传单个块:

private createAuthorizationHeader(canonicalizedString: string) {
  const str = CryptoJS.HmacSHA256(canonicalizedString, CryptoJS.enc.Base64.parse(this.config.accountKey));
  const sig = CryptoJS.enc.Base64.stringify(str);
  const authorizationHeader = `SharedKey ${this.config.accountName}:${sig}`;
  return authorizationHeader;
}
  

  
async putBlockBlob(containerName: str, blobPath: str, blobContent: str, blockIndex: number,) {
  const requestMethod = 'PUT';
    
  const urlPath = `${containerName}/${blobPath}`;
    
  const dateInRfc1123Format = new Date(Date.now()).toUTCString();
    
     const storageServiceVersion = '2019-12-12';
    
     const blobLength: number = blobContent.length;
    
     const blockId = Buffer.from(`block-${blockIndex}`).toString('base64');
    
     const blobType = 'BlockBlob';
    
     // StringToSign =
     //   VERB + "\n" +
     //   Content-Encoding + "\n" +
     //   Content-Language + "\n" +
     //   Content-Length + "\n" +
     //   Content-MD5 + "\n" +
     //   Content-Type + "\n" +
     //   Date + "\n" +
     //   If-Modified-Since + "\n" +
     //   If-Match + "\n" +
     //   If-None-Match + "\n" +
     //   If-Unmodified-Since + "\n" +
     //   Range + "\n" +
     //   CanonicalizedHeaders +
     //   CanonicalizedResource;
    
     const canonicalizedHeaders = `x-ms-date:${dateInRfc1123Format}\nx-ms-version:${storageServiceVersion}`;
     const canonicalizedResource = `/${this.config.accountName}/${urlPath}}\nblockid:${blockId}\ncomp:block`;
    
     const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
    
     const uriStr = `${urlPath}?comp=block&blockid=${blockId}`;
    
     const authorizationHeader = this.createAuthorizationHeader(stringToSign);
    
     const header = {
       'cache-control': 'no-cache',
       'x-ms-date': dateInRfc1123Format,
       'x-ms-version': storageServiceVersion,
       Authorization: authorizationHeader,
       'Content-Length': `${blobLength}`,
       'Content-Type': 'application/octet-stream',
     };
    
    
     try {
       return axios
         .create({baseURL: `https://${this.config.accountName}.blob.core.windows.net/`,})
         .request({
           method: requestMethod,
           url: uriStr,
           data: blobContent,
           headers: header,
         })
         .then((response) => response.data)
         .catch((err) => {
           throw err;
         });
     } catch (err) {
       console.log(err);
       throw err;
     }
   }
olhwl3o2

olhwl3o21#

我认为这个问题是由于RangeCanonicalizedHeaders之间缺少一个新行字符而引起的。
您可以尝试更改以下代码行吗:

const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;

致:

const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
ymdaylpp

ymdaylpp2#

它将帮助您将数据上载到Azure存储服务器
上载文件到服务器

export const uploadMedia = async (params: any, callBack: any) => {
  const SAS_URL: any = "https://${blobUrl}.blob.core.windows.net";
  const CONTAINER: any = "";
  const SAS_TOKEN: any = "";

  const { fileType, localUri } = params;
  const userId = "set user ID here";
  const fileName = String(fileType).concat(customIdGenerator(7));
  const assetPath = `${SAS_URL}/${CONTAINER}/${userId}/${fileName}`;
  HEADER["x-ms-blob-content-type"] = CONST_HEADER(fileType);
  return await RNFetchBlob.fetch(
    "PUT",
    `${assetPath}?${SAS_TOKEN}`,
    HEADER,
    RNFetchBlob.wrap(localUri)
  )
    ?.uploadProgress(callBack)
    .then(() => {
      return assetPath;
    });
};

文件类型= '视频'|影像|pdf格式

let params: any = {
      fileType: 'image',
      localUri: image,
    };

生成唯一性的自定义ID,也可以使用UUID

const customIdGenerator = (length: any) => {
  var result = "";
  var characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
};

设置不同文件的标题

const CONST_HEADER = (type: any) => {
  return type == 'image'
    ? `image/png`
    : type == 'video'
    ? 'video/mp4'
    : type == 'pdf' && 'application/pdf';
};

相关问题