MikeHelland
MikeHelland

Reputation: 1159

Trying to serve image stored in GAE Datastore originally created by canvas.toDataURL()

I have a canvas painted by the user.

In the JavaScript I do:

var data = canvas.toDataURL().substr(22);

// snipped code that sets up xhr POST to "d/"

var params = "img=" + encodeURIComponent(data);
xhr.send(params);

I substr(22) to get rid of "data:image/png;base64,"

Then in app engine I do:

doodle.setProperty("img", new Text(req.getParameter("img")));

So I am setting the img property of the doodle Entity to the canvas.toDataURL().substr(22)

Now, when I want to retrieve the image, I do:

if (debugimg) {
    resp.setContentType("text/plain");
    resp.getWriter().print(((Text)groove.getProperty("img")).getValue());
}
else {
     resp.setContentType("image/png;base64");
     resp.getWriter().print(((Text)groove.getProperty("img")).getValue());
}

But for the life of me, the image never comes up.

Here is an example. I drew this, and can save it and render it in JavaScript.

https://yougotadoodle.appspot.com/d.jsp?id=1483002

If I use debugimg, this is what is being saved:

http://yougotadoodle.appspot.com/d?id=1483002&img=true&debugimg=true

But when I try to serve it with setContentType("image/png;base64") or even just "image/png" you get a broken picture:

http://yougotadoodle.appspot.com/d?id=1483002&img=true

I have tried a few different things, including not substr(22)ing it. Any ideas?

I tried using a Blob(), so storing it like this:

doodle.setProperty("img", new Blob(req.getParameter("img").getBytes()));

and reading it like this:

resp.getWriter().print(((Blob)groove.getProperty("img")).getBytes());

But that seemed to spit out somethign like this:

[B@1f11e0f

Upvotes: 1

Views: 107

Answers (2)

stevep
stevep

Reputation: 959

Here are three code snippets that have worked for me on the JS side (jpg) through the put to a blob property. May not be optimal, but it does work. HTH. -stevep

Create canvas render:

imgFinalData = canvas.toDataURL('image/jpg', 1.0);

Setup variable for POST to GAE:

f64 = imgFinalData.substr(imgFinalData.indexOf(',')+1).toString();

Post to GAE (fd is an array used to store mutiple POST vars):

fd.push('bytes=' + escape(f64));
//Here is the call with fd that handles the post:
postXmlHttpRequest(url, fd.join('&'), handlePostFinal);

One the GAE side (Python):

Property that stores POST data (line from entity class):

bytes = db.BlobProperty(required=True, indexed=False)

How the post data is processed b/4 put:

data = urllib.unquote(self.request.get('bytes'))

data = data.replace(' ','+')

bytes = base64.b64decode(data + '=' * (4 - len(data) % 4))

Property line inside the entity statement for put:

bytes = db.Blob(bytes),

Upvotes: 0

Lipis
Lipis

Reputation: 21835

You have to decode this string before serving it as image/png because it is the Base64 encoded version.

I tested it locally in Python and your Hello SO! worked perfectly after decoding the given string. I'm not sure how to do it in Java but it should be fairly easy.

Upvotes: 0

Related Questions