我希望用户将大文件直接上传到Azure存储中。我有一个 Flask Python Web 应用程序,但由于大小限制,我不希望将文件上传到我的 Web 服务器。
当用户选择要上传的文件并单击上传按钮时,会发生以下情况:
blob_name = str(uuid.uuid4())
container_name = os.environ[default_container_name_setting]
sas = generate_blob_sas(account_name=service.account_name,
account_key=access_key,
container_name=container_name,
blob_name=blob_name,
permission=BlobSasPermissions(write=True, read=True, create=True),
expiry=datetime.utcnow() + timedelta(hours=2))
sas_url = 'https://' + service.account_name + '.blob.core.windows.net/' + container_name + '/' + blob_name + '?' + sas
return sas_url, blob_name
const chunkSize = 1024 * 1024 * 20;
const totalChunks = Math.ceil(file.size / chunkSize);
const blockIds = []; // Array to hold block IDs
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const blockId = btoa("block-" + i); // Base64 encode block ID
blockIds.push(blockId);
// Upload each chunk
const uploadResponse = await fetch(sas_url + "&comp=block&blockid=" + blockId, {
method: "PUT",
headers: {
"x-ms-blob-type": "BlockBlob",
"Content-Type": file.type
},
body: chunk
});
if (!uploadResponse.ok) {
return false;
}
}
到目前为止它有效。然而,下一步是告诉 Azure 将这些块放在一起,仍然通过 Javascript:
const commitResponse = await fetch(sas_url + "&comp=commitBlockList", {
method: "PUT",
headers: {
"Content-Type": "application/xml",
"x-ms-version": "2020-10-02",
"Content-Length": "0"
},
body: `<BlockList>${blockIds.map(id => `<Latest>${id}</Latest>`).join('')}</BlockList>`
});
if (!commitResponse.ok) {
throw new Error("Failed to commit blocks to blob.");
}
此时我总是收到 CORS 错误:
访问“https://xxx.blob.core.windows.net/container/e07d13fa-bcd6-45cf-9eea-3295e17dc567?se=2024-11-01T04%2A18%3B30Q&sp=rcw&sv=2024-11-”来自原点“http://localhost:4449”的 04&sr=b&sig=CudrFGsJ1HGnYo6Bh3K7WVAabgdOAsPteWq47XKuKDI%3D&comp=commitBlockList' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:无“Access-Control-Allow-Origin”标头存在于所请求的资源上。如果不透明响应满足您的需求,请将请求模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。
我知道我已经在 Azure 存储中正确设置了 CORS,因为上传部分可以正常工作。
在 Blob 服务选项卡下,我添加了 localhost 源,并使用允许的方法 GET、POST、OPTIONS 和 PUT。
我已尝试使用检索到的 Blob 名称重新生成另一个 SAS Url,但仍然收到 CORS 错误。
我错过了什么?
我不认为这个问题与 CORS 有关,因为如果它与 CORS 相关,那么您在上传块时会收到错误(
PUT BLOCK
和 PUT BLOCK LIST
操作都是 Put
请求。
我相信问题出在您的块 ID 上。根据文档,块 ID 必须具有相同的长度。考虑到您正在添加块索引来获取块 id,在第 10 个块之后,您的块 id 长度将会不同。
尽量保持块id的长度相同。您可以使用 GUID 作为块 ID 或在计数器前添加一些零,以保持块 ID 的长度相同。