如何从自定义表单将多个文件上传到 Magnolia CMS 资产应用程序

How can I upload multiple files into Magnolia CMS assets app from a custom form

短版

我有一个使用 Magnolia 的网络应用程序,我需要上传一条可能包含多个文件的评论,我想使用 AJAX,在将文件保存为资产之前我希望能够检查用户的权限,我想我需要一个自定义的基于 Java 的 REST 端点,我让它工作了,但是我在将 "jcr:data" 保存到资产中时遇到了问题。

长版

我有一个网络应用程序,我有注册用户(使用 PUR),我有不同的用户角色(为简单起见,假设 UserEditor),我有一个 Post 和一个 Comment 内容类型。每个用户可以创建一个Post并添加文件,每个Post包含创建者的 UUID、Comment UUID 数组和文件 UUID 数组(来自 Assets 应用程序),每个 Post 都有一个评论部分每个 Comment 都可以附加(零个或多个)文件。每个编辑者都可以post对每个Post发表评论,但是用户只能post评论自己Posts.

我的评论表单如下所示:

<form action="" method="post" id="comment-form" enctype="multipart/form-data">
  <input type="file" name="file" id="file" multiple />
  <textarea name="text"></textarea>
  <button type="button" onclick="sendComment();">Send</button>
</form>

我尝试使用 Java脚本模型来处理数据,我能够正确保存资产,但只有一个。我无法访问模型中的其他文件。

我尝试使用 AJAX 和 REST 端点解决它(并改善用户体验)。我选择不使用 Nodes 端点 API,因为我不知道如何解决权限问题。我知道我可以限制每个角色对 REST 的访问,但不是基于 Post 的所有权。所以我创建了自己的基于 Java 的端点(从文档中复制)。

sendComment() 函数的 Javascript 中,我创建了一个具有名称、扩展名、mimeType、...和数据等属性的对象。我在文档中读到您应该使用 Base64 格式发送数据,所以我使用 FileReader() 来实现:

var fileObject = {
  // properties like name, extension, mimeType, ...
}

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
   // this part is easy
};
xhttp.open("PUT", "http://localhost:8080/myApp/.rest/assets/v1/saveAsset", true);
xhttp.setRequestHeader("Content-type", "application/json");

var reader = new FileReader();
reader.onload = function() {
  fileObject.data = reader.result;
  // I also tried without the 'data:image/png;base64,' part by reader.result.split(",")[1];
  xhttp.send(JSON.stringify(fileObject));
};
reader.readAsDataURL(file);  //where file is the value of the input element.files[i]

在 Java 中,我创建了一个 POJO class,它具有与 javascript 对象相同的属性。包括一个字符串数据.

端点的代码如下所示:

public Response saveAsset(Asset file) {
  // Asset is my custom POJO class
  Session damSession;
  Node asset;
  Node resource;

  try {
    damSession = MgnlContext.getJCRSession("dam");
    asset = damSession.getRootNode().addNode(file.getName(), "mgnl:asset");

    asset.setProperty("name", file.getName());
    asset.setProperty("type", file.getExtension());
    resource = asset.addNode("jcr:content", "mgnl:resource");

    InputStream dataStream = new ByteArrayInputStream(file.getData().getBytes());
    ValueFactory vf = damSession.getValueFactory();
    Binary dataBinary = vf.createBinary(dataStream);

    resource.setProperty("jcr:data", dataBinary);
    resource.setProperty("fileName", file.getName());
    resource.setProperty("extension", file.getExtension());
    resource.setProperty("size", file.getSize());
    resource.setProperty("jcr:mimeType", file.getMimeType());

    damSession.save();

    return Response.ok(LinkUtil.createLink(asset)).build();
  } catch (RepositoryException e) {
    return Response.ok(e.getMessage()).build(); //I know it's not ok, but that's not important at the moment
  }
}

资产已创建,属性已保存 jcr:data。如果我上传图像然后通过 link 收到的响应或直接从资产应用程序下载它,它无法打开,我收到格式不受支持的消息。大小为 0,资产应用程序中未显示图像,似乎数据根本不存在,或者格式错误。

如何将文件或文件数据发送到 Java 端点?我应该如何接收它?有人知道我错过了什么吗?老实说,我不知道还能用它做什么。

谢谢

必须从 Base64 解码输入流。

InputStream dataStream = new ByteArrayInputStream(Base64.decodeBase64(file.getData().getBytes()));

...我只用了不到3个月的时间

在查看 REST 模块的源代码后注意到,为了解组二进制值,它必须编码为 Base64,所以我尝试解码它并开始工作。