如何使用服务器到服务器cloudkit.js在“资产”字段中保存记录

问题描述 投票:1回答:1

我想使用服务器到服务器的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下载音频时。音频文件为损坏播放。它出什么问题了。感谢您的回复。

node.js cloudkit cloudkit-web-services cloudkit-js
1个回答
0
投票

我遇到了同样的问题,并且找到了可行的解决方案!

[记住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客户端/服务),所以另一种选择是编写自己的例程来上传资产。

这两个选项似乎都不是特别好,但是如果您自己选择至少一个,则意味着客户无需采取其他步骤即可使用资产。

© www.soinside.com 2019 - 2024. All rights reserved.