裁剪图像并将其发送到jsf-bean,而无需进行不必要的数据传输



我想将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 &amp;&amp; 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");
}

尽管在网上可以找到一些误导性的答案,但一旦理解了这个过程,它实际上就很简单了。我希望这对将来的某个人有所帮助。

我使用的技术是:

  1. 拾取图像

  2. 一旦图像被拾取,就可以在不通过电线发送的情况下将其显示在一个小窗口中。

  3. 这里有几个选项,我选择了:当用户移动cropper矩形时,矩形的坐标会填充一个隐藏的输入字段。

  4. 将坐标发送到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 &amp;&amp; input.files[0]) {
            reader.readAsDataURL(input.files[0]);      
        }
    }
    $("#lolo\:imgInp").change(function(){
        readURL(this);
    });
</script>
  1. 一旦我们做到了这一点,它就有点依赖于所使用的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();
    }

最新更新