通过 PUT Block Azure Blob Storage 上传 Zip 文件格式不受支持

Zip File Unsupported Format while uploading it through PUT Block Azure Blob Storage

我正在使用以下代码使用 Azure Blob 存储中的 PUT block 请求类型将 zip 文件上传到我的 azure 容器。

const request = require('request')
const fs = require('fs')
const account = 'Enter your account here'
const containerName = 'stream-test-container'
const blobName = 'sampleBlob.zip'
const strTime = new Date().toUTCString()
const _ = require('lodash')
const uuid = require('uuid')

const requestBlockIdArray = []
const responseBlockIdArray = []
let readStreamEnded = false
const token = 'Enter your token here'
const readStream = fs.createReadStream('fiveMb.csv.zip')
let blobContent = ''
let contentLength = 0
const thresholdSize = 512 * 1024

readStream.on('data', function (chunk) {
  blobContent = blobContent + chunk
  contentLength = contentLength + chunk.length
  if (contentLength >= thresholdSize) {
    console.log('content length is:', contentLength)
    putBlock(blobContent, contentLength)
    contentLength = 0
    blobContent = ''
  }
})

readStream.on('end', () => {
  if (contentLength) {
    putBlock(blobContent, contentLength)
  }
  readStreamEnded = true
})

function callbackPutBlock (error, response, body) {
  console.log(response.statusCode, response.statusMessage, 'Block created')
  responseBlockIdArray.push(response.headers['x-ms-client-request-id'])
  console.log(response.headers['x-ms-client-request-id'], requestBlockIdArray[requestBlockIdArray.length - 1])
  if (readStreamEnded && responseBlockIdArray.length === requestBlockIdArray.length) {
    putBlockList()
  }
  if (error) {
    console.log(error)
  }
}

function callbackPutBlockList (error, response, body) {
  console.log(response.statusCode, response.statusMessage)
  if (response.statusCode === 201) {
    console.log('Blob Created')
  }
  if (error) {
    console.log(error)
  }
}

function putBlock (blobContent, contentLength) {
  const blockId = Buffer.from(uuid.v4().replace(/-/g, '')).toString('base64')
  requestBlockIdArray.push(blockId)
  const optionsPutBlock = {
    url: `https://${account}.blob.core.windows.net/${containerName}/${blobName}?comp=block&blockid=${blockId}`,
    headers: {
      Authorization:
      `Bearer ${token}`,
      'x-ms-date': strTime,
      'x-ms-version': '2019-02-02',
      'Content-Length': contentLength,
      'x-ms-client-request-id': blockId
    },
    body: blobContent
  }
  request.put(optionsPutBlock, callbackPutBlock)
}

function putBlockList () {
  const xmlBlockList = '<?xml version="1.0" encoding="utf-8"?><BlockList>' + (_.map(requestBlockIdArray, (id) => { return `<Latest>${id}</Latest>` })).join('') + '</BlockList>'
  const xmlBlockListLength = new TextEncoder().encode(xmlBlockList).length
  const optionsPutBlockList = {
    url: `https://${account}.blob.core.windows.net/${containerName}/${blobName}?comp=blocklist`,
    headers: {
      Authorization:
      `Bearer ${token}`,
      'x-ms-date': strTime,
      'x-ms-version': '2019-02-02',
      'Content-Length': xmlBlockListLength,
      'Content-Type': 'application/text-plain'
    },
    body: xmlBlockList
  }
  request.put(optionsPutBlockList, callbackPutBlockList)
}

但是当我尝试从 azure 下载上传的 zip 文件并尝试在我的系统中打开它时,它说该文件的格式不受支持。

我不确定是什么问题,是否与未通过content-type有关。因为我没有像 headers 中的文档那样传递它,因为它没有被提及。

参考文献:

https://docs.microsoft.com/en-us/rest/api/storageservices/put-block

https://docs.microsoft.com/en-us/rest/api/storageservices/put-block-list

请尝试更改以下代码行:

let blobContent = ''
let contentLength = 0
const thresholdSize = 512 * 1024

readStream.on('data', function (chunk) {
  blobContent = blobContent + chunk
  contentLength = contentLength + chunk.length
  if (contentLength >= thresholdSize) {
    console.log('content length is:', contentLength)
    putBlock(blobContent, contentLength)
    contentLength = 0
    blobContent = ''
  }
})

let blobContent = Buffer.from([]);
let contentLength = 0
const thresholdSize = 512 * 1024

readStream.on('data', function (chunk) {
  blobContent = Buffer.concat([blobContent, chunk], blobContent.length + chunk.length);
  contentLength = contentLength + chunk.length
  if (contentLength >= thresholdSize) {
    console.log('content length is: ', contentLength)
    putBlock(blobContent, contentLength)
    contentLength = 0
    blobContent = Buffer.from([]);
  }
})

基本上我已经改变了您处理 blob 内容的方式。我将数据保存为缓冲区并使用适当的缓冲区函数来添加内容。