I am creating a GAE app using WebApp2 that has a Data Object of Client. Each Client has a unique ID and I want to allow the user to upload one or many files associated with that particular Client object. I know that this is possible using blobstore, GCS, but am experimenting with Titan Files, which has the ability to use the blobstore backend while allowing me to create a quasi-file directory system for my users. I am fairly new to GAE programming, so any help would be greatly appreciated!
I am using the FormData object in order to append other useful information to my file (filename, and the directory path with a "folder" and a "sub-folder" that I want to write the file to). From the firebug console, my post appears to be firing correctly as I am seeing the post with lots of strange characters (the file) and other data I am appending to the file (the filename and path I want it written to as described above). That said, I am getting the following error:
Traceback (most recent call last):
File "C:\lib\webapp2-2.5.2\webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "C:\lib\webapp2-2.5.2\webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "C:\lib\webapp2-2.5.2\webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "C:\lib\webapp2-2.5.2\webapp2.py", line 1102, in __call__
return handler.dispatch()
File "C:\lib\webapp2-2.5.2\webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "C:\lib\webapp2-2.5.2\webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "C:\Users\Owner\Documents\vein\vann-vein\main.py", line 121, in post
myfile = self.request.post(self)
File "C:\lib\webob-1.1.1\webob\request.py", line 1238, in __getattr__
raise AttributeError(attr)
AttributeError: post
INFO 2015-03-21 13:55:19,667 module.py:666] default: "POST /uploadfile HTTP/1.1" 500 1469
I am fairly certain the issue is in my UploadHandler, but will provide other MVC elements for full context... I'm not clear on whether I am using the GET/POST correctly.
My HTML Form:
<div class="form-group">
<label class="control-label col-sm-4" for="clientNumber">Client Number*:</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="clientNumber" placeholder="Client 1111111" disabled>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" for="clientDocs">Client Docs:</label>
<div class="col-sm-8">
<input type="file" type="file" name="file" id="file"><br>
<button type="button" class="btn btn-info" id="clientDocsButton" onclick="addFile()" disabled>Add File</button><br>
</div>
</div>
My Javascript being called:
function addFile()
{
console.log("Pre-Instantiation.");
var filepath = window.location.pathname;
var subfolder = document.getElementById("clientNumber").value
var myfile = document.getElementById("file");
var filename = document.getElementById("file").value;
console.log("Post-Instantiation.");
var formData = new FormData();
formData.append('thefile', myfile.files[0]);
formData.append('filepath', filepath);
formData.append('subfolder', subfolder);
formData.append('filename', filename);
console.log("Pre-AJAX.");
console.log(typeof formData['thefile']);
$.ajax({
url: '/uploadfile', //Server script to process data
type: 'POST',
xhr: function() { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // Check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // For handling the progress of the upload
}
return myXhr;
},
//Ajax events
success: function(response) {
bootbox.alert(response);
},
error : function(xhr,errmsg,err) {
bootbox.alert(xhr.status);
},
data: formData,
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
})};
My Main - UploadHandler:
class UploadHandler(webapp2.RequestHandler):
def post(self):
myfile = self.request.post(self)
myfile = formData['thefile']
filepath = myfile['filepath']
subfolder = myfile['subfolder']
filename = myfile['filename']
files.File('/' + filepath + '/' + subfolder + '/' + filename).write(myfile)
self.response.write("Save successful")
Note: The files.File().write() method above is part of the Titan Files library which is being imported into my Main.py
You can get all the submitted data from the request object, via the get
method, no need to create any other objects:
class UploadHandler(webapp2.RequestHandler):
def post(self):
myfile = self.request.get('thefile')
filepath = self.request.get('filepath')
subfolder = self.request.get('subfolder')
filename = self.request.get('filename')
files.File('/' + filepath + '/' + subfolder + '/' + filename).write(myfile)
self.response.write("Save successful")