createBlockBlobFromStream() 覆盖现有内容而不是追加
Posted
技术标签:
【中文标题】createBlockBlobFromStream() 覆盖现有内容而不是追加【英文标题】:createBlockBlobFromStream() is overriding existing content instead of appending 【发布时间】:2021-09-18 05:12:50 【问题描述】:我们处理非常大的文件,因此我们将它们分成 20mb 的块,然后调用上传函数将它们上传到 blob 存储。我在节点 js 中调用 upload(),我发现上传时丢失了一些东西。每次只上传 20mb,我怀疑 nodejs 是覆盖内容而不是附加流。
有人可以帮忙解决吗?
const chunkSize = Number(request.headers["x-content-length"]);
const userrole = request.headers["x-userrole"];
const pathname = request.headers["x-pathname"];
var form = new multiparty.Form();
form.parse(request, function (err, fields, files)
if (files && files["payload"] && files["payload"].length > 0)
var fileContent = fs.readFileSync(files["payload"][0].path);
// log.error('fields',fields['Content-Type'])
fs.unlink(files["payload"][0].path, function (err)
if (err)
log.error("Error in unlink payload:" + err);
);
var size = fileContent.length;
if (size !== chunkSize)
sendBadRequest(response, "Chunk uploading was not completed");
return;
//converting chunk[buffers] to readable stream
const stream = Readable.from(fileContent);
var options =
contentSettings:
contentType: fields['Content-Type']
blobService.createBlockBlobFromStream(containerName, pathname, stream, size, options, error =>
);
标题:
X-id: 6023f6f53601233c080b1369
X-Chunk-Id: 38
X-Content-Id: 43bfdbf4ddd1d7b5cd787dc212be8691d8dd147017a2344cb0851978b2d983c075c26c6082fd27a5147742b030856b0d71549e4d208d1c3c9d94f957e7ed1c92
X-pathname: 6023f6ae3601233c080b1365/spe10_lgr311_2021-02-10_09-08-37/output/800mb.inc
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqodrlQNFytNS9wAc
X-Content-Name: 800mb.inc
【问题讨论】:
【参考方案1】:问题是您正在使用createBlockBlobFromStream
,它将覆盖 blob 的内容。此方法用于在单个请求中创建 blob(即完整的 blob 数据作为输入传递)。来自文档here
:
从流中上传块 Blob。如果 blob 已存在于 服务,它将被覆盖。为了避免覆盖,而是 如果 blob 存在则抛出错误,请传入 accessConditions 选项对象中的参数。
在您的情况下,您正在上传数据块。您需要做的是对您上传的每个块使用 createBlockFromStream
方法。
上传所有块后,您需要调用 commitBlocks
方法来创建 blob。
更新
我们如何生成blockId?
块 id 只是一个字符串。要记住的关键是,当您调用createBlockFromStream
时,您发送的每个块的块ID 的长度必须相同。例如,您不能使用1,2,3,4,5,6,7,8,9,10,11...
。您将不得不使用01,02,03,04,05,06,07,08,09,10,11...
之类的东西,以便它们具有相同的长度。您可以为此目的使用 GUID。此外,block id 的最大长度为 50 个字符。
它应该对所有人都是独一无二的吗?
是的。对于 blob,块 id 必须是唯一的,否则它将覆盖上一个使用相同 id 上传的块的内容。
你可以展示示例代码,以便我可以尝试类似的方式 实施?
请看here
。
基本上,这个想法非常简单:在客户端,您将文件分块并分别发送每个块。您要做的除了发送该数据外,您还将发送一个块 ID 字符串。您还需要在客户端保留该块 ID。您将对文件的所有块重复相同的过程。
一旦所有区块上传成功,您将向您的服务器再次发出请求并发送所有区块 ID 的列表。届时您的服务器将调用 commitBlocks
来创建 blob。
请注意,您上次请求中的块 ID 顺序很重要。 Azure 存储服务将使用此信息将 blob 拼接在一起。
【讨论】:
我们如何生成 blockId ,它应该对所有人都是唯一的吗?你可以展示示例代码,以便我可以尝试类似的方式来实现吗? 更新了我的答案。 HTH。 多一个请求是什么意思?不是在同一个API中吗?只需检查 eof 是否调用 commitblocks? 不确定你的意思。你能详细说明你的评论吗?提交块列表是与 Put 块操作分开的操作。使用提交块列表向 Azure 存储服务发出信号,以通过组合所有块来创建 blob。您可能会发现此链接有助于理解它:docs.microsoft.com/en-us/rest/api/storageservices/…。 实际上我对何时调用 commitblock() 感到有些困惑,它是在用于 createblockfromstream() 的同一 API 中还是需要调用单独的 API?以上是关于createBlockBlobFromStream() 覆盖现有内容而不是追加的主要内容,如果未能解决你的问题,请参考以下文章