我想使用服务器到服务器的cloudkit js。保存“资产”字段中的记录。资产字段是m4a音频。保存后,音频文件已损坏,无法播放
Apple的Doc不清楚Asset字段。在保存到数据库的记录中,资产字段的值必须是window.Blob类型。在上面的代码片段中,assetFile变量的类型为window.File。文件:https://developer.apple.com/documentation/cloudkitjs/cloudkit/database/1628735-saverecords
但是在nodejs中,没有Blob或。File,我用类似以下代码的缓冲区填充它:
var dstFile = path.join(__dirname,"../test.m4a");
var data = fs.readFileSync(dstFile);
let buffer = Buffer.from(data);
var rec = {
recordType: "MyAttachment",
fields: {
ext: { value: ".m4a" },
file: { value: buffer }
}
}
//console.debug(rec);
mydatabase.newRecordsBatch().create(rec).commit().then(function (response) {
if (response.hasErrors) {
console.log(">>> saveAttachFile record failed");
console.warn(response.errors[0]);
} else {
var createdRecord = response.records[0];
console.log(">>> saveAttachFile record success:", createdRecord);
}
});
记录成功保存。但是,当我从icloud.developer.apple.com/dashboard下载音频时。音频文件为损坏播放。它出什么问题了。感谢您的回复。
我遇到了同样的问题,并且找到了可行的解决方案!
[记住CloudKitJS需要您定义自己的fetch
方法,我实现了一个自定义方法来查看发生了什么。然后,当在自定义fetch
上载资产以编程方式设置断点后,我便附加了调试器,以查看发生了什么。
在遍历调用方之后,我发现当库嵌入到NodeJS中时,所有资产值都使用其toString()
方法only进行了转换。如果您想知道,可以通过缺少全局window
对象来确定。
当在toString()
上调用Buffer
时,其内容编码为UTF-8(默认情况下),这无疑导致资产格式错误。我不确定其背后的原因,因为node-fetch
支持Buffer
实例,因此我们需要想出一种方法来解决此问题,而不会破坏其他任何东西。
我发现的最简单的解决方法是在我们作为资产字段值传递的任何toString()
实例上交换Buffer
方法。您也可以在ReadableStream
上执行类似的操作,您可能应该这样做,以便在上传时不会将整个资产加载到内存中。
无论如何,这是实际的样子:
// Put this somewhere in your implementation
const swizzleBuffer = (buffer) => {
buffer.toString = () => buffer;
return buffer;
};
// Use this asset value instead
{ asset: swizzleBuffer(fs.readFileSync(path)) }
[请注意,此解决方法会以丑陋的方式更改Buffer
(这是必需的,以便它在instanceof
中传递node-fetch
断言)。设计一个不使用任何Buffer
参数的API可能是一个好主意,这样您就可以对自己创建的实例进行变异,并避免代码中其他地方的意外副作用。
此外,请确保在您的项目中供应CloudKitJS(在本地复制),因为将来的行为可能会发生变化。
原始答案
我遇到了同样的问题,并通过使用Base64对数据进行编码解决了该问题。看来,他们的SDK中存在一个错误,该错误会处理包含非ASCII字符的Buffer
实例(嗯,这似乎是有问题的)。
无论如何,尝试这样的事情:
const assetField = { value: Buffer.from(data.toString('base64')), 'ascii') }
旁注:
使用它们之前,您需要在设备上解码资产。没有编写自己的例程就无法有效地做到这一点,因为Data
/ NSData
实例中包含的方法要求所有数据都在内存中。
这是CloudKitJS的问题(而不是本机CloudKit客户端/服务),所以另一种选择是编写自己的例程来上传资产。
这两个选项似乎都不是特别好,但是如果您自己选择至少一个,则意味着客户无需采取其他步骤即可使用资产。