Uploading file to Google App Engine using new dev_appserver - python

Google App Engine documentation makes it appear very simple to get the contents of an uploaded file (self.request.get('user_file')), but while I can do this with old_dev_appserver.py, I cannot get it with the current dev_appserver.py (v1.9.2).
Here's a simple example that generates the incoming data:
<form name="myform" action="http://localhost:8080/sync?cmd=tester" enctype="multipart/form-data" method="post">
Username: <input type="file" name="user_file" />
<input type="submit" value="Submit" />
</form>
In old_dev_appserver.py, one could get the file in GAE via self.request.get('user_file'), but not with the latest (1.9.2) dev_appserver.py
WebApp2 says "Uploaded files are available as cgi.FieldStorage (see the cgi module) instances directly in request.POST." But, request.POST is empty, and cgi.FieldStorage() does not contain 'user_file' either.
Strangely, if I print out self.request.params, I do see an element in the UnicodeMultiDict that is (u'user_file', FieldStorage(u'user_file', u'myfile.ico')). But when I try to get that element, either via named access or just iterating over params, I cannot get it. Even if I do a Len(self.request.params) I get one less than what I see, and the 'user_file' element is missing. If I do this with old_dev_appserver, the Len(self.request.params) is correct.
How do I get user_file?

Figured it out (finally!). I had been logging elements of the request (params, body, etc.) as I sorted through other issues. But you can only instantiate a cgi.FieldStorage element once, so by the time I got to the actual self.request.get('user_file'), it was already gone.
Classic case in which removing the debugging actually makes it work.

Related

How to upload python script in django form and use it for some processing?

I want to upload python file through django form and read the function available inside and use it for processing.
Till now what i had done is:
Taken file from the user and saved in the media folder.
taken function name (so that i can use it if required for calling funtion)
Index.py
<form method="POST" enctype="multipart/form-data" action="/result">Enter function name
{% csrf_token %}
<input type="text" name="functionname"><br>
Upload your .py file here
<input type="file" name="functionfile">
<input type="submit" value="Submit">
</form>
views.py
def result(request):
if request.method == 'POST':
functionname=request.POST['functionname']
functionfile=request.FILES['functionfile']
fs= FileSystemStorage()
modulename=fs.save(functionfile.name,functionfile)
url=fs.url(modulename)
print(url)
return render(request,'result.html')
I don't have any clue how to use that the function of the uploaded file in the backend
Desired result would be something like.
for eg. example.py file contains a function
def add(data):
p=10+data
return p
i upload a example.py file
suppose in background i have d = 100
django calls result=add(d)
print the result
Any reference or resource will also be helpful.
Thanks
An simple approach would be use the normal file upload in django get the data in an action, launch a subprocess using docker which has python3 in it on the server side where you are running django application.
Why docker ?
It is safer to run even malicious code inside the docker container rather than on the server machine itself.
Other Ideas :
You can run the code and get result through online API's.
REF : https://github.com/saikat007/Online-Compiler-using-Django-python/blob/master/src/ide/views.py

How to control my webapp with Alexa

I built an alexa skill using Python with Flask_ask, which goes to my DB and retrieves information that I need and spells it out.
I am now trying to create a web UI which would have an option of asking the required question by typing it in or speaking directly to alexa. The web UI works easily as it redirects to the page I want as below :
#app.route('/getdog')
def getdog():
return render_template('mypage.html')
Ideally I would configure an intent which would trigger the change in webpage e.g.
#ask.intent('myintent')
def changepage():
getdog()
Any ideas how to handle this?
You can use use a simple HTML form with a text input box:<form method="POST" action="/changepage/">
Enter Your Query: <input type="text" name="intent_string" />
<input type="submit" value="Ask Alexa"/>
</form>
Your changepage url should call a method which handles calling other intents based on whatever string has been passes in the POST request.
If you not able to exactly match the required intent to call you can add a full text search and match with that

How to make Bottle refuse too big uploaded files?

Here is a way to accept upload with Bottle:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
</form>
and
from bottle import route, request
#route('/upload', method='POST')
def do_upload():
myfile = request.files.get('file')
size = len(myfile.read()) # oops the file is already read anyway!
if size > 1024*1024: # 1 MB
return "File too big"
However, with this technique a 500 MB file would be read anyway, before noticing it's a "too big file".
Question: how to prevent a Bottle server to even accept a too big uploaded file, without having to read it first (and waste bandwidth/memory!)?
If not possible with Bottle only, how to do it with Apache + mod_wsgi (I currently use this)?
Because you are using Apache, you can add to the Apache configuration the LimitRequestBody directive and specify the limit. The request will be rejected before it even gets to your Python code.
https://httpd.apache.org/docs/2.4/mod/core.html#limitrequestbody

Obtain 'post' form URL using .cgi file

File name: http://localhost/PostForm.html
<form method ="post" action="Information.cgi">
<table>
<tr><td>New date: </td><td> <input type ="date" name="DateNew" /></td></tr><br>
<tr><td>Old date: </td><td> <input type ="date" name="OldDate" /></td></tr><br>
</table>
<input type="submit" name = "submitname" value="Add Entry" />
</form>
Is there any way in which I can obtain the file name, which the post form is located on, from the .cgi python file?
I want to obtain the file name http://localhost/PostForm.html in the Information.cgi Python file.
Any help is greatly appreciated.
Yes, you can get that information, but not in a completely secure way. Browsers insert a header, Referer: which names the previous page.
Reference:
http://en.wikipedia.org/wiki/HTTP_referer
One way would be to grab the referrer info within Information.cgi using an Environmental Variable:
$ReferringPage = $ENV{HTTP_REFERER};
However, that's unreliable. Some users change browser settings to prevent sending referrer info amongst other possible situations where it might not pass.
You could also hard-code something in the referring page's form HTML that lets you know which page sent the referral:
<input type="hidden" name="wherefrom" value="Somepage.html">
Then, in your Information.cgi script, just grab that value and do whatever with it:
use CGI;
$in = new CGI;
$WhichPage = $in->{'wherefrom'};
This could be bypassed by the user or it might not work depending on your setup, but could work in some situations.

Uploading Files in webapp2/GAE

I need to upload and process a CSV file from a form in a Google App Engine application based on Webapp2 (Python) I understand I could use blobstore to temporary store the file but I am curious to know if there is a way to process the file without having to store it at all.
If you need to upload a file via webapp2 with an HTML form, the first thing you need to do is change HTML form enctype attribute to multipart/form-data, so the code snippet seems like:
<form action="/emails" class="form-horizontal" enctype="multipart/form-data" method="post">
<input multiple id="file" name="attachments" type="file">
</form>
In python code, you can read the file directly via request.POST, here's a sample code snippet:
class UploadHandler(BaseHandler):
def post(self):
attachments = self.request.POST.getall('attachments')
_attachments = [{'content': f.file.read(),
'filename': f.filename} for f in attachments]
The content of uploaded files is in self.request.POST in your handler, so you can get that content (assuming e.g the field for the uploaded file is named 'foo') with e.g
content = self.request.POST.multi['foo'].file.read()
So now you have the content as a string -- process it as you wish. This does of course assume the thing will fit in memory (no multi-megabyte uploads!-)...

Categories