GAE Python webapp2 image upload error - python

I am working on a project in which i am trying to upload a image on blob store. But i am getting this error
File "C:\Users\shaizi\PycharmProjects\simpletestapp\Update.py", line
51, in post
blob_info = upload_files[0]
IndexError: list index out of range
My html form code is
<form id="signup" method="post" action="/update" enctype="multipart/form-data">
<label>Change image:</label>
<input type="file" name="pict" ><br>
</form>
Python Code for uploading image to Blob store:
def post(self):
blobstore.create_upload_url('/post/signup')
upload_files = self.get_uploads('pict')
blob_info = upload_files[0]

Actually i have to set the action to Upload url.
<form id="signup" method="post" action="/post/signup" enctype="multipart/form-data">
<label>Change image:</label>
<input type="file" name="pict" ><br>
</form>

I think you have to use a form_url variable:
` <form method="post" action="{{ form_url }}" accept-charset="UTF-8"
enctype="multipart/form-data">`
You get this variable from the appengine with your backend code:
class UploadPage(BaseRequestHandler):
def get(self):
form = UploadForm()
self.render('upload.html', {
'form': form,
'form_url': blobstore.create_upload_url('/upload_form'),
})

In my case, with multi-part forms, I am getting file data as follows:
self.request.get('<name_in_form>')
For your case, it should be:
self.request.get('pict')
In any case, if possible, try to avoid using blobstore, as Google recommends using Cloud Storage, as blobstore looks like will be deprecated in the future, couple of references:
https://cloud.google.com/appengine/docs/python/blobstore/
Google Blobstore versus Google cloud storage
Regards.

Related

Django upload file using get method

I would like to upload a single file or files at a time using get method.
I have already done with the post method and working fine. But for some reason i would like to do the file upload using get method using command line.
The below code is which i have already tried to get the string from get method and i can able to get the varValue as string. But i would like to get the file using get method.
def home(request):
if request.method == 'GET':
varValue = request.GET.get('myfile', '')
print(varValue)`
HTML code:
<form method="GET" enctype="multipart/form-data">
<input type="file" name="myfile" accept="image/*" multiple>
<button type="submit">Upload files</button>
Try This Method
for filename, file in request.FILES.iteritems():
name = request.FILES[filename].name
A dictionary-like object containing all uploaded files. Each key in FILES is the name from the . Each value in FILES is an UploadedFile.
<form method="GET" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile">
<button type="submit">Upload File</button>
</form>
Found the solution using the post method itself. By skipping the csrf token we can do the command line script execution method.
Python views.py code below
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def home(request):
if request.method == 'POST':
uploaded_file = request.FILES['myfile']
fs = FileSystemStorage()
name = fs.save(uploaded_file.name, uploaded_file)
print(name)
return render(request, "home.html")
HTML code:
<body>
<form method="POST" enctype="multipart/form-data">
<input type="file" name="myfile" accept="image/*" multiple>
<button type="submit">Upload files</button>
</body>
python code for file upload using post method:
import requests
files = {'myfile': open('d:\\20190819-140341-627485.png','rb')}
y = requests.post("http://127.0.0.1:8000",files=files)

flask html input format

I am trying to read a file in using python/Flask and display it at the click of a button. To view the file, a return function like this works fine:
return redirect(url_for('uploaded_file',filename=filename))
But I am trying to implement in HTML to view file at a click. Something like this:
<form><input action="redirect(url_for etc. ??)" type=submit value=viewFile> </form>
What would be the correct syntax for action?
Thanks for any hint.
The action attribute should go on <form>, not <input>. The value of action should just be the URL of your route which accepts the file. Assuming you're using Jinja2, something like this:
Jinja2:
<form action="{{url_for('upload')}}" enctype="multipart/form-data">
<input type="file" name="view_file">
<input type="submit" value="Upload">
</form>
Python:
#app.route('/upload', methods=['POST'])
def upload():
# Handle upload and save to disk here..
return redirect(url_for('uploaded_file', filename=filename))
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
See also http://flask.pocoo.org/docs/0.11/patterns/fileuploads/ (it looks like you are already working from that example..)
This code worked for me to pass filename to html form input.
python:
...
return render_template('view.html', cat = filename)
html (view.html):
<!doctype html>
<form action="{{url_for('uploaded_file', filename=cat)}}" enctype="multipart/form-data">
<input type=submit value='view file'>
</form>

upload file to google storage using Python Google App engine API

I am following Massimiliano Pippi's Python for Google App engine. In chapter 3, we are trying to upload a file that the user of my app select thanks to this html code:
<div class="form-group">
<label for="uploaded_file">Attached file:</label>
<input type="file" id="uploaded_file" name="uploaded_file">
</div>
And from the python part, in my MainHandler on webapp2, I get the request content using:
def post(self):
uploaded_file = self.request.POST.get("uploaded_file", None)
file_name = getattr(uploaded_file, 'filename')
file_content = getattr(uploaded_file, 'file', None)
content_t = mimetypes.guess_type(file_name)[0]
bucket_name = app_identity.get_default_gcs_bucket_name()
path = os.path.join('/', bucket_name, file_name)
with cloudstorage.open(path, 'w', content_type=content_t) as f:
f.write(file_content.read())
The problem is that the variable uploaded_file is handled as if it was a file by Massimiliano Pippi, but my Python tells me that this variable is a unicode containing the name of the file. Therefore, when I try file_name = getattr(uploaded_file, 'filename'), I get an error.
Obviously, the code in the book is false, how can I fix it?
Ok so after Tim's advice, I chcked the doc of WebOb and notice that in the html file, I should have put enctype="multipart/form-data" as follows:
<form action="" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="uploaded_file">Attached file:</label>
<input type="file" id="uploaded_file" name="uploaded_file">
</div>
</form>
Instead of:
<form action="" method="post">
<div class="form-group">
<label for="uploaded_file">Attached file:</label>
<input type="file" id="uploaded_file" name="uploaded_file">
</div>
</form>

Transferring from Blob to Cloud Storage

I've transferred my App-Engine from BlobStorage to Cloud-Storage. This works finde with these Upload-Code:
Upload.py:
...
upload_url = blobstore.create_upload_url('/upload', gs_bucket_name="my-default-bucket")
...
my_upload_template.html:
...
<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" name="submit" value="Submit">
</form>
...
Upload.py:
class UploadBlobHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
file_info = self.get_file_infos()[0]
self.response.out.write(file_info.gs_object_name)
self.redirect("/download/serve" + file_info.gs_object_name)
it worked great. But it's upload not only in the Google Cloud Storage-Bucket. It's uploaded in den Blob Storage too. (Can check when you go to https://appengine.google.com and click Blob Viewer.)
Is that the right way? Is it right? Or do I something wrong?
If I understood you correctly... you're using the Blobstore API to save to your Google Cloud Storage?
If that is what you're doing, then yes you're doing correctly, and yes it will save a copy of your document in the Blobstore.

How to upload a file with django (python) and s3?

I'm looking for a way to upload a file to s3. I am using django. I am currently using amazon's python library for uploading along with the following code:
View:
def submitpicture(request):
fuser = request.session["login"]
copied_data = request.POST.copy()
copied_data.update(request.FILES)
content_type = copied_data['file'].get('content-type')
ffile = copied_data['file']['content']
key = '%s-%s' % (fuser, ''.join(copied_data['file']['filename'].split(' ')))
site_s3.save_s3_data(key, ffile, content_type)
Template:
<form action="/submitpicture/" method="POST">
<input type="file" id="file" name="file" />
<input type="submit" value="submit" />
</form>
However, when I actually try to run it i get the following error:
"Key 'file' not found in <QueryDict: {}>"
#MultiValueDictKeyError
I really don't see what I'm doing wrong. Can someone point me in the right direction?
Edit: Just in case someone wonders, I am planning on adding some validation after I get the actual upload working.
You will have to provide the enctype attribute to the FORM element (I've been bitten by this before). For example, your FORM tag should look like:
<form action="/submitpicture/" method="POST" enctype="multipart/form-data" >
Without the enctype, you will find yourself with an empty request.FILES.
Instead of doing this manually I would take a look at the storage backend David Larlet has written for Django, django-storages
Adding enctype="multipart/form-data" seems like something that's worth mentioning in the "File Uploads" section of the django docs (http://docs.djangoproject.com/en/dev/topics/http/file-uploads/). Thoughts?

Categories

Resources