如何从自定义表单将多个文件上传到 Magnolia CMS 资产应用程序
How can I upload multiple files into Magnolia CMS assets app from a custom form
短版
我有一个使用 Magnolia 的网络应用程序,我需要上传一条可能包含多个文件的评论,我想使用 AJAX,在将文件保存为资产之前我希望能够检查用户的权限,我想我需要一个自定义的基于 Java 的 REST 端点,我让它工作了,但是我在将 "jcr:data" 保存到资产中时遇到了问题。
长版
我有一个网络应用程序,我有注册用户(使用 PUR),我有不同的用户角色(为简单起见,假设 User 和 Editor),我有一个 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,所以我尝试解码它并开始工作。
短版
我有一个使用 Magnolia 的网络应用程序,我需要上传一条可能包含多个文件的评论,我想使用 AJAX,在将文件保存为资产之前我希望能够检查用户的权限,我想我需要一个自定义的基于 Java 的 REST 端点,我让它工作了,但是我在将 "jcr:data" 保存到资产中时遇到了问题。
长版
我有一个网络应用程序,我有注册用户(使用 PUR),我有不同的用户角色(为简单起见,假设 User 和 Editor),我有一个 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,所以我尝试解码它并开始工作。