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

时间:2019-04-13 14:54:14

标签: node.js cloudkit cloudkit-web-services cloudkit-js

我想使用服务器到服务器的cloudkit js。保存资产字段中的记录。
 资产字段是m4a音频。保存后,音频文件无法播放

  

“苹果文档”的“资产”字段不清楚。
  在保存到数据库的记录中,“资产”字段的值必须是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);
    }
  });

记录成功保存。 success 但是当我从icloud.developer.apple.com/dashboard下载音频时。
音频文件已播放
它出什么问题了。感谢您的答复。

1 个答案:

答案 0 :(得分:2)

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

记住CloudKitJS需要您定义自己的fetch方法,所以我实现了一个自定义方法以查看发生了什么。然后,我在自定义fetch上附加了调试器,以检查通过它的数据。

单步调用者之后,我发现当库嵌入到NodeJS中时,所有资产值都使用其toString()方法 转换。这取决于缺少全局window对象。

toString()上调用Buffer时,其内容编码为UTF-8(默认),这会导致二进制资产格式错误。如果您在node-fetch实现中使用fetch,则它支持Bufferstream.Readable,因此此toString()调用只会带来伤害。

我发现的最简单的解决方法是在作为资产字段值传递的任何toString()Buffer实例上交换stream.Readable方法。顺便说一下,您可能应该使用stream.Readable,以便在上传时不会将整个资产加载到内存中。

无论如何,这是实际的样子:

// 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(因为Buffer显然无法扩展)。设计一个不使用Buffer参数的API可能是个好主意,这样您就可以对仅由您自己创建的实例进行变异,以避免代码中其他地方的意外副作用。

此外,请确保在您的项目中供应CloudKitJS(在本地复制),因为将来的行为可能会改变。

原始答案

我遇到了同样的问题,并通过使用Base64编码数据解决了该问题。看来,他们的SDK中存在一个错误,该错误会处理Buffer个包含非ASCII字符的实例(嗯,这似乎是有问题的)。

无论如何,尝试这样的事情:

const assetField = { value: Buffer.from(data.toString('base64')), 'ascii') }

旁注

您需要先在设备上解码资产,然后再使用它们。没有编写自己的例程就无法有效地做到这一点,因为Data / NSData实例中包含的方法要求所有数据都在内存中。

这是CloudKitJS(而不是本地CloudKit客户端/服务)的问题,因此另一种选择是编写自己的例程来上传资产。

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