Question :
I’m trying to save a cropped image after the user uploads the image. The upload works fine and I can save the cropped image too, but something strange is happening. The image is only trimmed and saved if I put the image path directly into the image attribute of the imageCropper
component, something like this:
<p:imageCropper value="#{imageCropperBean.croppedImage}" image="/imagens/prof/imageName.jpg" initialCoords="225,75,300,125" id="imageCropper"/>
If I try to get the name of the image (I get the image name when I upload it) from my managed bean, the imageCropper
does not work, something like this:
<p:imageCropper value="#{imageCropperBean.croppedImage}" image="/imagens/prof/#{imageCropperBean.currentImageName}" initialCoords="225,75,300,125" id="imageCropper"/>
Here is my code:
uploadImageCropper.xhtml
<html
xmlns_h="http://xmlns.jcp.org/jsf/html"
xmlns_p="http://primefaces.org/ui">
<h:head>
<title>Image upload with crop</title>
</h:head>
<h:body>
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{imageCropperBean.fileUploadAction}" update="imageCropper" />
<h:panelGrid columns="2">
<p:imageCropper value="#{imageCropperBean.croppedImage}" image="/imagens/prof/#{imageCropperBean.currentImageName}" initialCoords="225,75,300,125" id="imageCropper"/>
<p:graphicImage id="localCroppedImage" value="/imagens/prof/#{imageCropperBean.newImageName}.jpg" />
</h:panelGrid>
<p:commandButton value="Crop" action="#{imageCropperBean.crop}" update="localCroppedImage"/>
</h:form>
</h:body>
ImageCropperBean.java
@ManagedBean
@RequestScoped
public class ImageCropperBean {
private CroppedImage croppedImage;
private String currentImageName;
private String newImageName;
public ImageCropperBean() {
setCurrentImageName("no_image.jpg");
}
public void fileUploadAction(FileUploadEvent event) {
try {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
FacesContext aFacesContext = FacesContext.getCurrentInstance();
ServletContext context = (ServletContext) aFacesContext.getExternalContext().getContext();
String realPath = context.getRealPath("/");
File file = new File(realPath + "/imagens/prof/");
file.mkdirs();
byte[] arquivo = event.getFile().getContents();
String caminho = realPath + "/imagens/prof/" + event.getFile().getFileName();
setCurrentImageName(event.getFile().getFileName());
FileOutputStream fos = new FileOutputStream(caminho);
fos.write(arquivo);
fos.close();
} catch (Exception ex) {
System.out.println("Erro no upload de imagem" + ex);
}
}
public String crop() {
if(croppedImage == null)
return null;
setNewImageName(getRandomImageName());
ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
String newFileName = servletContext.getRealPath("") + File.separator + "imagens" + File.separator + "prof" + File.separator + getNewImageName() + ".jpg";
FileImageOutputStream imageOutput;
try {
imageOutput = new FileImageOutputStream(new File(newFileName));
imageOutput.write(croppedImage.getBytes(), 0, croppedImage.getBytes().length);
imageOutput.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getRandomImageName() {
int i = (int) (Math.random() * 100000);
return String.valueOf(i);
}
//getter and setters
}
Answer :
Vanilson, I know this question was asked more than a month ago, but I decided to contribute to help people with the same problem.
The solution
Change the scope of @RequestScoped
to @ViewScoped
in the managed bean and everything will work.
Explanation
Your code does the upload of the image in a request and a ajax
event updates the imageCropper
into another. When you update imageCropper
it tries to read the image property in a new request ; in this new request property, the currentImageName
property will have the value default ( no_image.jpg
) instead of the value stored in the request %. Using fileUploadAction
the stored value will be kept between requests since there was no navigation between views .
Source: Response from optimus.prime à this question in the PrimeFaces forum.
Dear @ vanilson-lourenco, the solution shown below is not exactly what you want because it runs on the Client (JavaScript) but might solve your problem.
HTML
<img id="myImage" src="http://i.stack.imgur.com/HNvh8.jpg"><scriptsrc="http://cdn.alloyui.com/2.0.0/aui/aui-min.js"></script>
<link href="http://cdn.alloyui.com/2.0.0/aui-css/css/bootstrap.min.css"
rel="stylesheet"></link>
JS
var myCropper = {};
YUI().use('aui-image-cropper', function(Y) {
myCropper = new Y.ImageCropper({
cropHeight: 200,
cropWidth: 200,
srcNode: '#myImage',
x: 50,
y: 50
}
).render();
}
);
// seu código JS adicional
See the details of this Framework ALLOYUI that uses Yahoo’s YUI 3.
Test Image: