使用 Java Servlet 保存 HTML5 <canvas> 图像

Posted

技术标签:

【中文标题】使用 Java Servlet 保存 HTML5 <canvas> 图像【英文标题】:Saving HTML5 <canvas> Image w/ Java Servlet 【发布时间】:2013-06-15 06:03:01 【问题描述】:

我知道已经有很多关于 *** 的问题,但我已经搜索了尽可能多的东西,但我的代码还没有工作,所以我终于发布了我自己的问题。

我的目标是将网页中 html5 &lt;canvas&gt; 上的图像保存到服务器上的文件中。我希望使用 Java servlet 来实现这一点。

我的 javascript 像这样抓取画布图像数据:

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
    
);

我的 Java servlet 尝试像这样保存图像:

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

servlet 成功写出一个图像文件,但它没有正确打开并且其中不包含所有图像数据。我的 Javascript 成功抓取了&lt;canvas&gt; 图像数据,如下所示:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACWCAYAAABkW7XSAAAgAElEQVR4nJTa51NcaZ7ge+QBIZBAwgoEkvDeJt577733njRk4r3PhDRAJkkmiTdCXqWqUlVXtZl209OzvWN27t17/5rvvoCu7t6ZmN158YnfcyJOnIjz4vnGEyeOWdRmAP+RaI3fT2I0PiTtBJF9KKD8TTKVb5IpPosl+zCMdFMgKQY/otTPCFl3IljhSPiWB5E7XkToPAnVexNq8CVyP5Cwg0CCDwII2vfHx+TDC6MXz3df8mznGc7bTthu2PJwxRrrufvcnzbn4bQFjnNWuK3a4r3hQrDmBSGbLwlRvyR0w5OQ9ZeErHsRsuFLyIYvQeu+BCh88Zf74K/wxU8ZgL8qEH9VEAHq0L8RqAkjeCuCsO1IwrVRhGujCNNdCdVFEayNJEQXdUUfTYg+mmC9AH99BL47YfjuhOK7G4KvIRhfQzDee4F47QXibQrCe98f730/vPf98N3zw9/kT+B+IG . . . [and so on]

任何想法我在这里缺少什么?我觉得我犯了一些我无法发现的小错误。

【问题讨论】:

到目前为止,我什至不知道 JavaScript 能够将画布编码为图像......你为什么不尝试将数据作为请求参数传递并使用request.getParameter("imgBase64") ? 另外我会将 JS 简化为 $.post(screenshotCreateUrl, imgBase64: imageDataURL ); 【参考方案1】:

通过使用 multipart/form-data 内容类型,完成了相同的任务并能够使其工作(没有 jQuery,并在 maclema 的回复的帮助下):

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);

要异步发送,或者如果您有更多部分要发送(例如多个图像),或者如果您想处理响应,请参阅How to send multipart/form-data form content by ajax (no jquery)?

您的 servlet 的 doPost 方法如下所示:

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-commons-codec
  FileOutputStream fos = new FileOutputStream("img.png");
  fos.write(bImg);

希望这会有所帮助。

【讨论】:

@Steph 如果这解决了您的问题,您可以将其标记为最佳答案 :-) 非常感谢您的帮助。它很好地解决了我的问题。我自己永远无法解决这个问题。【参考方案2】:

您想要获取的是 post 参数,而不是请求的内容数据。此外,您还需要剥离编码信息。

试试这个:

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();

【讨论】:

感谢您的帮助,我试过了,但仍然无法完全正常工作。 testOutput.png 文件正在被写出并在图像查看器中打开,但图像似乎是空白的。如果我在文本编辑器中打开文件,我可以看到里面有很多数据,但它的格式一定不能完全正确。

以上是关于使用 Java Servlet 保存 HTML5 <canvas> 图像的主要内容,如果未能解决你的问题,请参考以下文章

java:servlet接收图片,并把它保存到数据库中

将图像从android上传到java servlet并保存

用于 chrome 中 html5 视频的 Servlet 流式传输 mp4

笔记之_java整理servlet

为 Android/iOS 打包的 HTML5 应用程序的 JSP/Servlet 会话

Java Servlet+Objective-c图上传 步骤详细