I know there are a lot of StackOverflow questions about this already, but I've searched through as many as I could find and have yet to get my code working, so I am finally posting my own question.
My goal is to save an image that is on an HTML5 <canvas>
in my webpage to a file on my server. I was hoping to acplish this using a Java servlet.
My JavasScript grabs the canvas image data like this:
var canvas = document.getElementById("screenshotCanvas");
var context = canvas.getContext("2d");
var imageDataURL = canvas.toDataURL('image/png');
// I'm not if I need to do this, I've tried several different ways to no avail
//imageDataURL = imageDataURL.replace("image/png", "image/octet-stream");
//imageDataURL = imageDataURL.replace(/^data:image\/(png|jpeg);base64,/,"");
$.ajax({
url: screenshotCreateUrl,
type: "POST",
data: { imgBase64: imageDataURL },
error: function(jqXHR, textStatus, errorThrown) {
// Handle errors
},
success: function(data, textStatus, jqXHR) {
// Do some stuff
}
});
My Java servlet tries to save the image like so:
try {
HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request);
HttpServletRequestWrapper requestWithWrapper = (HttpServletRequestWrapper) wrappedRequest.getRequest();
byte[] contentData = requestWithWrapper.getContentData();
byte[] decodedData = Base64.decodeBase64(contentData);
FileOutputStream fos = new FileOutputStream("testOutput.png");
fos.write(decodedData);
fos.close();
} catch(Exception e) {
// Handle exceptions
}
The servlet successfully writes out an image file, but it does not open properly and does not contain all the image data in it. My Javascript successfully grabs the <canvas>
image data, which looks like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAgAElEQVR4nJTa51NcaZ7ge+QBIZBAwgoEkvDeJt577733njRk4r3PhDRAJkkmiTdCXqWqUlVXtZl209OzvWN27t17/5rvvoCu7t6ZmN158YnfcyJOnIjz4vnGEyeOWdRmAP+RaI3fT2I0PiTtBJF9KKD8TTKVb5IpPosl+zCMdFMgKQY/otTPCFl3IljhSPiWB5E7XkToPAnVexNq8CVyP5Cwg0CCDwII2vfHx+TDC6MXz3df8mznGc7bTthu2PJwxRrrufvcnzbn4bQFjnNWuK3a4r3hQrDmBSGbLwlRvyR0w5OQ9ZeErHsRsuFLyIYvQeu+BCh88Zf74K/wxU8ZgL8qEH9VEAHq0L8RqAkjeCuCsO1IwrVRhGujCNNdCdVFEayNJEQXdUUfTYg+mmC9AH99BL47YfjuhOK7G4KvIRhfQzDee4F47QXibQrCe98f730/vPf98N3zw9/kT+B+IG . . . [and so on]
Any ideas what I am missing here? I feel like i am making some tiny mistake that I just can't spot.
I know there are a lot of StackOverflow questions about this already, but I've searched through as many as I could find and have yet to get my code working, so I am finally posting my own question.
My goal is to save an image that is on an HTML5 <canvas>
in my webpage to a file on my server. I was hoping to acplish this using a Java servlet.
My JavasScript grabs the canvas image data like this:
var canvas = document.getElementById("screenshotCanvas");
var context = canvas.getContext("2d");
var imageDataURL = canvas.toDataURL('image/png');
// I'm not if I need to do this, I've tried several different ways to no avail
//imageDataURL = imageDataURL.replace("image/png", "image/octet-stream");
//imageDataURL = imageDataURL.replace(/^data:image\/(png|jpeg);base64,/,"");
$.ajax({
url: screenshotCreateUrl,
type: "POST",
data: { imgBase64: imageDataURL },
error: function(jqXHR, textStatus, errorThrown) {
// Handle errors
},
success: function(data, textStatus, jqXHR) {
// Do some stuff
}
});
My Java servlet tries to save the image like so:
try {
HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request);
HttpServletRequestWrapper requestWithWrapper = (HttpServletRequestWrapper) wrappedRequest.getRequest();
byte[] contentData = requestWithWrapper.getContentData();
byte[] decodedData = Base64.decodeBase64(contentData);
FileOutputStream fos = new FileOutputStream("testOutput.png");
fos.write(decodedData);
fos.close();
} catch(Exception e) {
// Handle exceptions
}
The servlet successfully writes out an image file, but it does not open properly and does not contain all the image data in it. My Javascript successfully grabs the <canvas>
image data, which looks like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAgAElEQVR4nJTa51NcaZ7ge+QBIZBAwgoEkvDeJt577733njRk4r3PhDRAJkkmiTdCXqWqUlVXtZl209OzvWN27t17/5rvvoCu7t6ZmN158YnfcyJOnIjz4vnGEyeOWdRmAP+RaI3fT2I0PiTtBJF9KKD8TTKVb5IpPosl+zCMdFMgKQY/otTPCFl3IljhSPiWB5E7XkToPAnVexNq8CVyP5Cwg0CCDwII2vfHx+TDC6MXz3df8mznGc7bTthu2PJwxRrrufvcnzbn4bQFjnNWuK3a4r3hQrDmBSGbLwlRvyR0w5OQ9ZeErHsRsuFLyIYvQeu+BCh88Zf74K/wxU8ZgL8qEH9VEAHq0L8RqAkjeCuCsO1IwrVRhGujCNNdCdVFEayNJEQXdUUfTYg+mmC9AH99BL47YfjuhOK7G4KvIRhfQzDee4F47QXibQrCe98f730/vPf98N3zw9/kT+B+IG . . . [and so on]
Any ideas what I am missing here? I feel like i am making some tiny mistake that I just can't spot.
Share Improve this question asked Jun 18, 2013 at 20:55 StephSteph 2,1957 gold badges31 silver badges44 bronze badges 2- Up to now I even didn´t know that JavaScript was able to encode the canvas as image.... Why don´t you try to pass the data as request-parameter and just get it with request.getParameter("imgBase64") ? – cljk Commented Jun 18, 2013 at 21:18
- Also I would simplify the JS to $.post(screenshotCreateUrl, {imgBase64: imageDataURL }); – cljk Commented Jun 18, 2013 at 21:20
2 Answers
Reset to default 3Had the same task and was able to make it work (without jQuery and with the help of maclema's reply), by using multipart/form-data content type:
var xhr = new XMLHttpRequest();
xhr.open("post", "AddressOfYourServlet", false);
var boundary = Math.random().toString().substr(2);
xhr.setRequestHeader("content-type",
"multipart/form-data; charset=utf-8; boundary=" + boundary);
var multipart = "--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=myImg\r\n" +
"Content-type: image/png\r\n\r\n" +
canvas.toDataURL("image/png") + "\r\n" +
"--" + boundary + "--\r\n";
xhr.send(multipart);
To go asynchronously or if you have more parts to send (e.g. multiple images) or if you want to work with the response, see How to send multipart/form-data form content by ajax (no jquery)?
Your servlet's doPost method would look something like:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Part part = request.getPart("myImg");
BufferedReader br = new BufferedReader(new InputStreamReader(part.getInputStream(),
Charset.forName("utf-8")));
String sImg = br.readLine();
sImg = sImg.substring("data:image/png;base64,".length());
byte[] bImg64 = sImg.getBytes();
byte[] bImg = Base64.decodeBase64(bImg64); // apache-mons-codec
FileOutputStream fos = new FileOutputStream("img.png");
fos.write(bImg);
}
Hope this helps.
You want to get the post parameter and not the content data of the request. As well you will also need to strip the encoding information.
Try this:
try {
HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request);
HttpServletRequestWrapper requestWithWrapper = (HttpServletRequestWrapper) wrappedRequest.getRequest();
String imageString = wrappedRequest.getParameter("imgBase64");
imageString = imageString.substring("data:image/png;base64,".length);
byte[] contentData = imageString.getBytes();
byte[] decodedData = Base64.decodeBase64( contentData );
FileOutputStream fos = new FileOutputStream("testOutput.png");
fos.write(decodedData);
fos.close();
} catch(Exception e) {
// Handle exceptions
e.printStackTrace();
}