我想将jquery cropper生成的图像上传到bean字段。
客户端我发现了这个:
<p:fileUpload
id="imgInp"
mode="simple" allowTypes="/(.|/)(gif|jpe?g|png)$/"/>
<img id="blah" src="#" alt="your image" />
<p:imageCropper image="" />
<script>
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
function readURL(input) {
if (input.files && input.files[0]) {
reader.readAsDataURL(input.files[0]);
}
}
$("#imgInp").change(function(){
readURL(this);
});
</script>
它在不上传的情况下显示了图像,但我无法将其放入cropper中。所以我使用了一个jquery cropper,但我不确定如何在bean中获得它(不需要经过servlet,因为它不是一次性使用的)。换句话说,我需要通过ajax向bean发送一个img。
否则我会使用primeface,但它必须穿过电线,如果可能的话,我想避免。从我看到的例子中,图像是服务器上的静态内容。我真的必须将图像保存在服务器上吗?我不能把它作为对象,并把UploadedFile
转换成cropper会接受的东西吗?
看起来像这样:
<p:fileUpload
mode="advanced" allowTypes="/(.|/)(gif|jpe?g|png)$/"
fileUploadListener="#{bean.uploadPicListenner}"
update="cropper"/>
<h:panelGroup id="cropper" >
<p:imageCropper image="#{bean.img}"/>
</h:panelGroup>
public void uploadPicListenner(FileUploadEvent e) {
img = e.getFile();
RequestContext.getCurrentInstance().update("ptform:cropper");
}
尽管在网上可以找到一些误导性的答案,但一旦理解了这个过程,它实际上就很简单了。我希望这对将来的某个人有所帮助。
我使用的技术是:
-
拾取图像
-
一旦图像被拾取,就可以在不通过电线发送的情况下将其显示在一个小窗口中。
-
这里有几个选项,我选择了:当用户移动cropper矩形时,矩形的坐标会填充一个隐藏的输入字段。
-
将坐标发送到bean并在服务器端裁剪它。
我这样做是因为我想使用的cropper jquery库没有将图像转换为64进制,只是给出了一个矩形的坐标。然而,如果将来有人想直接发送裁剪后的图像,我想这真的很容易。就像我做的一样,只是你必须把裁剪后的图像作为字符串基64放在一个隐藏的输入文本中(而不是矩形坐标,这在下面解释),并在服务器端将其转换回原来的位置,仅此而已。(我不知道这有多有效/安全)。至少这解决了我与素数面的问题,素数不想多次通过网络发送不必要的数据。
1.首先,让我们显示图像,而不将其发送到服务器
此时,当图像显示时,如果您检查img的src标记内部,您将看到它是图像的数据,如base64:
src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAQABAAD/2wCEAAYEBQYFBAYGBQ…
<h:form id="lolo" enctype="multipart/form-data">
<p:fileUpload
value="#{adminCreateTeam.teamImg}"
mode="simple" allowTypes="/(.|/)(gif|jpe?g|png)$/"/>
<img id="blah" src="#" alt="your image" />
</h:form>
<script>
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
function readURL(input) {
if (input.files && input.files[0]) {
reader.readAsDataURL(input.files[0]);
}
}
$("#lolo\:imgInp").change(function(){
readURL(this);
});
</script>
- 一旦我们做到了这一点,它就有点依赖于所使用的jquery裁剪库。我用了一个插页。有了这个,我们想要得到裁剪矩形的坐标。使用坐标数据,我们填充一个隐藏的输入,并将其发送回bean,然后在java端重新操作它
或者,更好的解决方案(imo)是使用一个库,该库裁剪图像并将数据客户端作为基64,填充隐藏字段并将其发送回bean,然后将基64转换为图像。这些步骤中的每一个都非常简单,可以在stackoverflow上找到。
由于我想使用cropper库,我用了第一种方法:
这是在表单中添加的:
<h:inputHidden value="#{adminCreateTeam.rect}"/>
<p:commandButton value="submit" action="#{adminCreateTeam.picTest}" ajax="false"/>
这是更新的加载:
// with this the hidden field is gonna be populated by the
// cropping rectangle data.
var $imageCrop = $('#blah').cropper({
aspectRatio: 1/1,
viewMode: 1,
crop: function(e) {
// Output the result data for cropping image.
// string with all the data delimited by /
$('#lolo\:hiddenB64').val(e.x + '/' + e.y + '/' + e.width + '/' + e.height);
}
});
//So the image changes in the cropper when a new image is picked
reader.onload = function (e) {
$imageCrop.cropper('replace',e.target.result);
}
我们用java裁剪图像
public void picTest() {
//getting coord.
String data[] = rect.split("/");
try (InputStream in = new ByteArrayInputStream(teamImg.getContents())) {
BufferedImage bImageFromConvert = ImageIO.read(in);
// line under this crops. It's possible there is a zoom to figure out, I didn't check yet. Seemed correct on first and only try. In any case you'll figure it out
// surely the parsing shouldn't be here but I need to sleep real bad.
BufferedImage dest = bImageFromConvert.getSubimage((int)(Double.parseDouble(data[0])), (int)(Double.parseDouble(data[1])),
(int)(Double.parseDouble(data[2])), (int)(Double.parseDouble(data[3])));
// path to the folder
Path folder = Paths.get(dirs.getString("imgTeams"));
String filename = "team_pic";
String extension = FilenameUtils.getExtension(teamImg.getFileName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);
ImageIO.write(dest, "jpeg", file.toFile());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}