We all know that App Engine limits you to 1 MB for most input/output requests. But with the recent BlobStore API, you are allowed to upload large files in full by POSTing to a dynamically generated URL.
According to the sample, here is what the HTML form would look like:
self.response.out.write('<html><body>')
self.response.out.write('<form action="%s" method="POST"
enctype="multipart/form-data">' % upload_url)
self.response.out.write("""Upload File:
<input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form></body></html>""")
But how can we do this asynchronously using JavaScript techniques introduced with HTML5? This is a snippet of what I have so far:
xhr.open("POST", post_url); // the post URL given by App Engine
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.setRequestHeader('X-File-Name', file.fileName);
// After loading the binary data (last time we only read as base64 string)
// Tell xhr to start the upload
myBinaryDataReader.addEventListener("loadend", function(evt){
xhr.sendAsBinary(evt.target.result);
}, false);
// Initiate the binary reading on the file, when finished it will
// upload asynchronously
myBinaryDataReader.readAsBinaryString(file);
You'll notice that this technique sends the raw binary file as the POST
body. Which is fine, it works without needing the BlobStore for up to 1 MB. In Python, to read the file, I just use:
img_data = self.request.body # got my image data now
However, with BlobStore, I'm supposed to use
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
But I'm not using an HTML form with input type=file, I'm using an XmlHttpRequest -- how can I make App Engine "think" it is a file from an HTML form, and thus "grab" the file data?
My code, unmodified, results in an error
File "C:\Python26\lib\cgi.py", line 583, in keys
raise TypeError, "not indexable"
TypeError: not indexable