Azure PUT Block List 400错误?原因及解决指南
2025-01-14 08:35:22
Azure PUT Block List 返回 400 错误
使用 Azure Blob 存储时,经常需要先上传多个数据块(block),随后通过 PUT Block List
操作提交这些块来创建一个完整的 blob。 当这一步操作返回 HTTP 400 错误时,通常意味着请求的某些部分存在问题。下面将分析可能的原因并给出解决办法。
常见错误原因及处理方法
1. BlockId
不匹配或缺失
PUT Block List
操作的关键在于提供的 block id 需要与之前上传的块 id 完全一致。哪怕一个字母或数字的差异,或者上传的块未在 block list 中列出都会导致 400 错误。
处理方法: 仔细检查你之前上传块的 block id 与 block list 中的 block id 是否完全相同,同时检查是否遗漏任何需要提交的块。
示例代码 (Python):
import hashlib
import base64
import requests
import datetime
def upload_block(storage_account, container, blob_name, block_id, content, sas_token):
url = f"https://{storage_account}.blob.core.windows.net/{container}/{blob_name}?comp=block&blockid={block_id}{sas_token}"
headers = {
"x-ms-blob-type": "BlockBlob",
"x-ms-version": "2019-12-12" # 需确保 version 一致
}
response = requests.put(url, data=content, headers=headers)
response.raise_for_status()
return response
def commit_block_list(storage_account, container, blob_name, block_ids, sas_token):
url = f"https://{storage_account}.blob.core.windows.net/{container}/{blob_name}?comp=blocklist{sas_token}"
headers = {
"x-ms-version": "2019-12-12", # 确保版本一致
"Content-Type": "application/xml",
}
block_list_xml = f"""<?xml version="1.0" encoding="utf-8"?>
<BlockList>
{''.join([f'<Latest>{id}</Latest>' for id in block_ids])}
</BlockList>"""
response = requests.put(url, headers=headers, data=block_list_xml.encode("utf-8"))
response.raise_for_status() # 错误将在此处抛出
return response
if __name__ == "__main__":
storage_account_name = "your_storage_account_name"
container_name = "your-container-name"
blob_name = "test_blob.txt"
sas_token = "?your_sas_token"
# Example data to upload in multiple blocks.
block1_content = b"This is block one."
block2_content = b" This is block two."
block1_id = base64.b64encode(hashlib.md5(block1_content).digest()).decode()
block2_id = base64.b64encode(hashlib.md5(block2_content).digest()).decode()
# Uploading Blocks.
upload_block(storage_account_name, container_name, blob_name, block1_id, block1_content,sas_token)
upload_block(storage_account_name, container_name, blob_name, block2_id, block2_content,sas_token)
# Commit block List
block_ids_to_commit = [block1_id,block2_id] # Ensure that ID are correctly placed and passed into list
commit_block_list(storage_account_name,container_name,blob_name,block_ids_to_commit,sas_token)
print("Successfully Uploaded Block list")
- 说明: 代码展示了先上传 block,并产生唯一
blockid
的方法, 然后构建正确的 blocklist 并使用 PUT 请求发送.请注意代码中使用了 version "2019-12-12" 这是一个需要特别注意的问题. 代码演示了一个完整的流程,可以方便开发者快速检查错误。
2. x-ms-version
版本不匹配
在对 Azure 存储执行 API 操作时, x-ms-version
header 非常重要,它决定了所使用的 API 版本。若此版本与 Blob 存储账户允许的或你期望使用的版本不匹配,同样会收到 400 错误。
处理方法: 检查发送 PUT Block
和 PUT Block List
请求时是否使用了相同的 x-ms-version
, 同时确保使用的是 Azure Blob Storage 账户支持的版本。通常建议使用最新版本以获得最新的功能与改进。
示例代码 (Shell):
# 上传block
curl -v -X PUT "https://<storage_account>.blob.core.windows.net/<container>/<blob_name>?comp=block&blockid=<block_id>&<sas_token>" \
-H "x-ms-version: 2020-10-02" -H "Content-Length: <content_length>" -H "x-ms-blob-type: BlockBlob" -d "<your_block_data>"
#提交blockList
curl -v -X PUT "https://<storage_account>.blob.core.windows.net/<container>/<blob_name>?comp=blocklist&<sas_token>" \
-H "x-ms-version: 2020-10-02" -H "Content-Type: application/xml" -d "<your_blocklist_xml>"
# 其中 <your_blocklist_xml> 是你定义的 XML 例如:
# <?xml version="1.0" encoding="utf-8"?>
#<BlockList>
#<Latest><blockid1></Latest>
# <Latest><blockid2></Latest>
# </BlockList>
- 说明: 示例演示了通过 shell 工具执行命令,这里明确展示
x-ms-version
header 在不同的 PUT 请求中是一致的,并注意block list xml 的构成形式。务必确保在 block 上传和提交 blocklist 时x-ms-version
的一致性。
3. XML 格式不正确
PUT Block List
操作需要接收一个 XML 格式的块列表,格式错误或语法问题将直接导致请求失败。 XML 内容需要明确标明 <BlockList>
根元素和每个块对应的 <Latest>
标签。
处理方法: 验证生成的 XML 内容符合规范,检查标签是否闭合,块 id 是否正确放置。 借助在线 XML 验证工具可以检查 XML 格式是否有误。
示例代码 (JavaScript):
function generateBlockListXML(blockIDs) {
let xmlString = `<?xml version="1.0" encoding="utf-8"?><BlockList>`;
blockIDs.forEach(blockID => {
xmlString += `<Latest>${blockID}</Latest>`;
});
xmlString += `</BlockList>`;
return xmlString;
}
let blockIDs = ["blockid1", "blockid2"];
let blockListXML = generateBlockListXML(blockIDs);
console.log(blockListXML);
// PUT Request - 请根据实际需求填充 URL 和请求设置。
// fetch("https://<your-storage-account>.blob.core.windows.net/<container>/<blob_name>?comp=blocklist&<sas-token>",{
// method:"PUT",
// headers: {
// "x-ms-version": "2020-10-02", // Ensure consistent version.
// "Content-Type": "application/xml"
// },
// body: blockListXML
// }).then((response)=>{
// if (!response.ok) {
// throw new Error('HTTP error, status = ' + response.status);
// } else {
// console.log('提交成功');
// }
// })
- 说明: 展示一个生成 blocklist XML 的 Javascript 函数,并演示了如何发送 Put 请求,注意这里只是个演示。
xmlString
中要注意blockId
是否为<Latest>
标签包裹,<BlockList>
根元素和 encoding,请严格检查。
4. Content-Length 头不正确
发送 XML 内容时,Content-Length
请求头的值必须正确指示请求体的长度,任何偏差都会引发 400 错误。
处理方法: 每次生成 XML 后,需计算准确的长度,并将该值设置到请求头中。某些 HTTP 客户端库会自动设置这个值。 使用工具来自动生成 HTTP 头会帮助避免潜在的问题。
5. 请求URL 编码
URL 中若包含了特殊字符,例如 +
、空格等,需要使用 URL 编码进行转义,确保这些特殊字符不会破坏请求的格式。特别是当 block ID 使用了 Base64 编码后。
处理方法: 在生成请求 URL 时,请务必对任何包含特殊字符的部分进行编码, 以避免服务端无法解析。大多数 HTTP 库提供了相关的 API 进行 URL 编码。
- 安全建议 : 使用共享访问签名 (SAS) 或其他授权方法进行身份验证时, 要小心地保管你的连接信息,避免泄露给未授权方,同时定期轮换SAS token,减小泄露风险.
相关资源
如果问题依旧,可能需要参考 Azure 存储服务的官方文档,以及相关SDK的使用指南. 这些资源能帮助更深入了解 Blob 存储的操作细节以及API的最佳实践。例如, 可以在 Microsoft Azure Documentation中搜索 “PUT Block List”, 查看对应文档。