views:

20735

answers:

12

I am planning to create a web app that allows users to downgrade their visual studio project files. However, It seems Google App Engine accepts files uploading and flat file storing on the Google Server through db.TextProperty and db.BlobProperty.

I'll be glad anyone can provide code sample ( both the client and the server side) on how this can be done, thanks

+1  A: 

You can not store files as there is not a traditional file system. You can only store them in their own DataStore (in a field defined as a BlobProperty)

There is an example in the previous link:

class MyModel(db.Model):
  blob = db.BlobProperty()

obj = MyModel()
obj.blob = db.Blob( file_contents )
Guido
A: 

There's no flat file storing in Google App Engine. Everything has to go in to the Datastore which is a bit like a relational database but not quite.

You could store the files as TextProperty or BlobProperty attributes.

There is a 1MB limit on DataStore entries which may or may not be a problem.

Dave Webb
+8  A: 

Client side upload:

<form enctype="multipart/form-data" action="/upload">
<input type="file" name="myfile" />
<input type="submit" />
</form>

Server side storing:

class MyModel(db.Model):
   blob = db.BlobProperty()


def upload(request) :
    # TODO add your own validations
    file_contents = request.FILES['myfile'].read() # django only
    obj = MyModel()
    obj.blob = db.Blob( file_contents )
    obj.put()

def download(request, id) :
    obj = MyModel.all().filter("id", id).get()
    # TODO write obj.blob to the response

It is untested copy and paste. I use Django. The URL mapping is up to you :)

Guido
Thanks! Seem to be exactly what I wanted
Ngu Soon Hui
WRONG. Check your answer before you post.OP this definitely should not be marked as the correct answer. It has several mistakes in it. It is not because it uses django either. Test your code.
bobobobo
Shouldn't "form encoding=" be "form enctype=" ?
Bill the Lizard
FILES['myfile'] is a dict object and doesn't have read().
Shay Erlichmen
This answer is COMPLETELY wrong. please fix it or delete it
Shay Erlichmen
request.FILES : A dictionary-like object containing all uploaded files. Each key in FILES is the name from the <input type="file" name="" />. Each value in FILES is an UploadedFile object containing the following attributes: read(num_bytes=None), name, size, chunks(chunk_size=None). As I said in the answer, the code is not tested but the main idea is right and it should be really close to work, so I think it could help other people. Please feel free to edit the answer if you know how to fix it.
Guido
+5  A: 

There is a thread in Google Groups about it:

Uploading Files

With a lot of useful code, that discussion helped me very much in uploading files.

+17  A: 

In fact, this question is answered in the App Egnine documentation. See an example on Uploading User Images.

HTML code, inside <form></form>:

<input type="file" name="img"/>

Python code:

class Guestbook(webapp.RequestHandler):
  def post(self):
    greeting = Greeting()
    if users.get_current_user():
      greeting.author = users.get_current_user()
    greeting.content = self.request.get("content")
    avatar = self.request.get("img")
    greeting.avatar = db.Blob(avatar)
    greeting.put()
    self.redirect('/')
jetxee
this example is given in google's site too dude, explaine something new
Dhaval dave
A: 

Thank you Guido for the answer, but I am having problem with this statement:

file_contents = request.FILES['myfile'].read()

I am getting this error "AttributeError: FILES" and I have to use

file_contents = request.get('myfile')

to make it work

Is request.FILES valid in GAE ?

Do you know where the documentation for this is? I couldn't find anything on request.FILES in GAE website.

Thank you.


Details of the error

Traceback (most recent call last):
  File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 501, in __call__
    handler.post(*groups)
  File "c:\helloworldform01\helloworld.py", line 52, in post
    greeting.file1 = self.request.FILES['myfile1'].read()
  File "C:\Program Files\Google\google_appengine\lib\webob\webob\__init__.py", line 500, in __getattr__
    raise AttributeError(attr)
AttributeError: FILES
request.FILES is for django only, for the default (webob - do what you described).
Michael Neale
+2  A: 

If your still having a problem, check you are using enctype in the form tag

No:

<form encoding="multipart/form-data" action="/upload">

Yes:

<form enctype="multipart/form-data" action="/upload">
TinjaNurtle
I was getting an encoding error before I implemented your answer
Jader Dias
A: 

Personally I found the tutorial described here useful when using the Java run time with GAE. For some reason, when I tried to upload a file using

<form action="/testservelet" method="get" enctype="multipart/form-data">
    <div>
        Myfile:<input type="file" name="file" size="50"/>
    </div>

    <div>
        <input type="submit" value="Upload file">
    </div>
</form>

I found that my HttpServlet class for some reason wouldn't accept the form with the 'enctype' attribute. Removing it works, however, this means I can't upload any files.

It may be because you are using the get method, try setting it to post instead. I'm not certain if it'll work but it's worth trying.
slashnick
+3  A: 

Google has released a service for storing large files. Have a look at blobstore API documentation. If your files are > 1MB, you should use it.

jbochi
+1  A: 

I try it today, It works as following:

my sdk version is 1.3.x

html page:

<form enctype="multipart/form-data" action="/upload" method="post" > 
<input type="file" name="myfile" /> 
<input type="submit" /> 
</form> 

Server Code:

file_contents = self.request.POST.get('myfile').file.read() 
Bili
Doesn't work for me.
Honza Pokorny
A: 

I have observed some strange behavior when uploading files on App Engine. When you submit the following form:

<form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" name="img" />
    ...
</form>

And then you extract the img from the request like this:

img_contents = self.request.get('img')

The img_contents variable is a str() in Google Chrome, but it's unicode in Firefox. And as you now, the db.Blob() constructor takes a string and will throw an error if you pass in a unicode string.

Does anyone know how this can be fixed?

Also, what I find absolutely strange is that when I copy and paste the Guestbook application (with avatars), it works perfectly. I do everything exactly the same way in my code, but it just won't work. I'm very close to pulling my hair out.

Honza Pokorny
:D The form said: mutlipart/form-data instead of multipart/form-data. Chrome is smart enough to correct the typo, Firefox isn't.
Honza Pokorny
A: 

Is there a Java version of the above code?