How could i upload a file to a server without using FieldStorage in python?
Here is a toy program snippet that should help get you started. Try reading RFC 1867 as well for more guidance.
#!/usr/bin/python
import os
import sys
buf = sys.stdin.read(512)
print "Content-type: text/html\n\n";
print '<html>'
print '''
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="f">
<input type="submit">
</form>
'''
print buf
print '</html>'
You can use os.environ.items() to get a list of environment variables, notably CONTENT_LENGTH and CONTENT_TYPE (specifically the boundary key/pair) so you know where the demarcation points are for the uploaded content.
Related
I have data with a .txt extension . I want to read the file, but the result of his error result < cStringIO.StringO object at 0x7f5078d18068 > What 's wrong ?
My file
Abedus
Accer
Chrome
HTML
<html>
<body>
<form enctype="multipart/form-data" action="http://localhost/cgi-bin/my.py" method="post">
<p>File: <input type="file" name="filename"></p>
<p><input type="submit" value="Upload"></p>
</form>
</body>
</html>
CGI Python
#!/usr/bin/python
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
data = form['filename'].file
print "Content-Type: text/plain"
print ""
print "result %s" % data,
I have a Python script and I want to create a very simple HTML form with 3 fields (username, password and an ID) and a submit button.
When I click Submit I just want to pass these three parameters into my Python script and run the script.
I tried to do it using CGI. I created a cgi-bin folder and added my test.py file in there. The Python code is the following:
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
username = form.getvalue('username')
password = form.getvalue('password')
room_id = form.getvalue('room_id')
#More code here...
Then I created an index.html file:
<!DOCTYPE html>
<html>
<body>
<form name="search" action="/[path to file]/test.py" method="get">
Username: <input type="text" name="username"> <br>
Password: <input type="password" name="password"> <br>
Room ID: <input type="text" name="room_id"> <br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Finally, I added a server.py file:
import CGIHTTPServer
CGIHTTPServer.test()
I run the server.py file and go to 0.0.0.0:8000. I gave the input but when I click Submit the python code is printed in the form and it is not executed.
I am looking for the simplest and fastest way to make this HTML form execute the script. It is only for test purposes and I do not want to spend time creating a complex web application.
Is CGI a good idea? If yes, what am I doing wrong?
Utilizing the Tornado library within Python I have come across a very unusual error. It seems that when I have decorated my file upload handler with '#tornado.web.stream_request_body' the webserver throws the error:
WARNING:tornado.general:403 POST /upload (ip-address): '_xsrf' argument missing from POST
WARNING:tornado.access:403 POST /upload (ip-address) 1.44ms
The code governing the upload is as follows:
#tornado.web.stream_request_body
class Upload(BaseHandler):
def prepare(self):
print self.request.headers
def data_received(self,chunk):
print chunk
#tornado.web.authenticated
def post(self):
self.redirect("/")
where my BaseHandler is a web.RequestHandler subclass with various helper functions (retrieving user info from cookies and whatnot).
Within my HTML template, I have the appropriate xsrf function call as seen here:
<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
{% raw xsrf_form_html() %}
<input type="file" name="upFile" required/>
<button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>
and is generating the proper xsrf input within the browser:
<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
<input type="hidden" name="_xsrf" value="2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367"/>
<input type="file" name="upFile" required/>
<button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>
When I turn off xsrf_cookies within the webserver settings, all is well and everything functions as normal. However I feel that this is not ideal.
While xsrf_cookies is set to False, if given a text file called "stuff.txt" with a body of "testfile" the output is:
------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="_xsrf"
2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367
------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="upFile"; filename="stuff.txt"
Content-Type: text/plain
testfile
------WebKitFormBoundary4iHkIqUNgfqVErRB--
From that output, my guess is that the xsrf value is being captured by the stream_request_body and not passed to the appropriate xsrf validation class.
Any help on this would be greatly appreciated. Thank you in advance!
Tornado does not currently (as of version 4.1) support streaming multi-part uploads. This means that uploads you wish to stream must be simple PUTs, instead of a POST that mixes the uploaded data with other form fields like _xsrf. To use XSRF protection in this scenario you must pass the XSRF token via an HTTP header (X-Xsrf-Token) instead of via a form field. Unfortunately this is incompatible with non-javascript web form uploads; you must have a client capable of setting arbitrary HTTP headers.
For my forum, I tried uploading a file with html using:
<form action="profiles.py" method="post">
<label class="labelOne" for="pics">Change your Profile pic </label>
<input type="file" name="uploadField" />
My python function takes that file, creates a file under userprofiles, and writes the data to it:
file = open('../data/accounts/userprofiles/'+str(form['name'].value)+'/'+'profilepics', 'w+')
file.write(str(form.getvalue('uploadField')))
file.close()
So, If I want burger.jpg to be my picture, I upload it, python takes that and creates a file with that name burger.jpg using w+ and then it writes the data to it(which should be the image).
However for some reason, I get no image.
What should I try next?
Set the enctype of your form to multipart/form-data
<form action="profiles.py" method="post" enctype="multipart/form-data">
I am beginning with python CGI programming, using mod_python in apache2, and am trying to retrieve the GET fields in HTTP requests to a simple .py page.
The code:
#!/usr/bin/python
import cgi
import cgitb; cgitb.enable()
print 'Content-type: text/html\n'
print '''
<html>
<body>
'''
form = cgi.FieldStorage()
l = len(form.keys())
print "<p>%s field(s) set.</p>" % l
print '''
</body>
</html>
'''
The page prints "0 field(s) set." What could be wrong here? So far in my search for an answer I haven't find a parameter in mod_python of apache2 that would block the transmission of GET fields to the CGI script.
cgi.FieldStorage relies on a multipart form being POSTed, not sent via GET. Change the method on your form and make sure you have multipart in the form tags:
<form action="" method="post" multipart>
<input type="file" name="file">
<input type="submit" name="submit" value="Submit">
</form>
When you use the GET method, cgi.FieldStorage just grabs the query string, which will at best give you the name of the file you're trying to submit.