Upload data URL to Django server
Asked Answered
P

2

6

I am trying to do this in Django (async upload a canvas as an image file). I'm using (a slightly modified version of) the javascript found in the demo, which rolls its own XHRHttpRequest, but I fail to find any evidence of the upload on the server side.

The canvas data is being extracted like this:

img_data = canvas.toDataURL('image/jpeg').replace("data:image/jpeg;base64,", "");

This is the xhr header:

xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=multipartformboundary1352769538973');

This is the POST content:

--multipartformboundary1352769538973
Content-Disposition: form-data; name="user_file"; filename="test.jpeg"
Content-Type: application/octet-stream

/9j/4AAQSkZJRgABAgAAAQABAAD/2wCEAAUDAwUHD...snipping image data...
AJRRRQAUtJS018gA/9k=
--multipartformboundary1352769538973
Content-Disposition: form-data; name="username"


--multipartformboundary1352769538973
Content-Disposition: form-data; name="challenge"


--multipartformboundary1352769538973
Content-Disposition: form-data; name="galleryPath"


--multipartformboundary1352769538973--

When I ask Django to show me the request object it sees, this is what I get:

<WSGIRequest
path:/samlite/save_frame,
GET:<QueryDict: {}>,
POST:<QueryDict: {u'username': [u''], u'challenge': [u''], u'galleryPath': [u'']}>,
COOKIES:{},
META:{'ARCHFLAGS': '-arch i386',
 'Apple_PubSub_Socket_Render': '/tmp/launch-wL0OpX/Render',
 'Apple_Ubiquity_Message': '/tmp/launch-ox20mG/Apple_Ubiquity_Message',
 'COMMAND_MODE': 'unix2003',
 'CONTENT_LENGTH': '34323',
 'CONTENT_TYPE': 'multipart/form-data; boundary=multipartformboundary1352769538973',
 'DISPLAY': '/tmp/launch-KzsfWx/org.x:0',
 'DJANGO_SETTINGS_MODULE': 'simsam.settings',
 'DYLD_LIBRARY_PATH': '/Applications/bitnami-djangostack/apps/django/lib/python2.7/site-packages:/Applications/bitnami-djangostack/apps/django/lib/python2.7/site-packages:/Applications/bitnami-djangostack/python/lib:/Applications/bitnami-djangostack/mysql/lib:/Applications/bitnami-djangostack/sqlite/lib:/Applications/bitnami-djangostack/apache2/lib:/Applications/bitnami-djangostack/common/lib:',
 'GATEWAY_INTERFACE': 'CGI/1.1',
 'HOME': '/Users/chris',
 'HTTP_ACCEPT': 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
 'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
 'HTTP_ACCEPT_LANGUAGE': 'en,en-US;q=0.9,ja;q=0.8,fr;q=0.7,de;q=0.6,es;q=0.5,it;q=0.4,pt;q=0.3,pt-PT;q=0.2,nl;q=0.1',
 'HTTP_CONNECTION': 'Keep-Alive',
 'HTTP_HOST': 'localhost:8000',
 'HTTP_REFERER': 'http://localhost:8000/samlite/',
 'HTTP_USER_AGENT': 'Opera/9.80 (Macintosh; Intel Mac OS X 10.7.5) Presto/2.12.388 Version/12.10',
 'LANG': 'en_US.UTF-8',
 ...less interesting stuff snipped...
}>

So the normal POST key/value pairs are getting through, but based on this, I expected to see a response.FILES dictionary. Can anyone point me in the right direction?

Peursem answered 13/11, 2012 at 1:30 Comment(0)
O
1

Django doesn't include the FILES dictionary in the repr() output. Try accessing it anyway:

print request.FILES

In the Django source, you can see that path, GET, POST, COOKIES, and META are included, but not FILES.

Order answered 13/11, 2012 at 2:25 Comment(0)
P
5

Turns out the whole thing was vastly easier if I just POSTed canvas.toDataURL(), trimmed the string as above, and did this on the server:

img_data = img_string.decode("base64")
img_file = open("photo.jpg", "wb")
img_file.write(img_data)
img_file.close()

Edit per Sean's comment

What I sent in the POST was just the base64 data part, which means remove these leading characters from the result of toDataURL():

data:image/jpeg;base64,

This could be done client side or server side, the point is that you need to drop that stuff before you decode the base64 characters to binary and write the image file.

Peursem answered 14/11, 2012 at 12:40 Comment(1)
FYI to others: "trim the string as above" means removing "data:image/jpeg;base64," per img_data = canvas.toDataURL('image/jpeg').replace("data:image/jpeg;base64,", "");Unmanly
O
1

Django doesn't include the FILES dictionary in the repr() output. Try accessing it anyway:

print request.FILES

In the Django source, you can see that path, GET, POST, COOKIES, and META are included, but not FILES.

Order answered 13/11, 2012 at 2:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.