Google app engine with python - python

I'm new to Google app engine with python ,please help me!
Here is my html code:
<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>
<div class="form-group">
<button class="btn-primary" type="submit">Save note</button>
</div>
</form>
Here is my python code:
def post(self):
uploaded_file = self.request.POST.get('uploaded_file')
file_name = getattr(uploaded_file, 'filename', None)
file_content = getattr(uploaded_file, 'file', None)
if uploaded_file:
self.response.out.write(uploaded_file)
self.response.out.write(file_name)
self.response.out.write(file_content)
I deploy my project to Google app engine and visit the website. I choose a picture and click the submit button, it can show uploaded_file(file's name). But, file_name and file_content show None.
If I modify my code :
def post(self):
uploaded_file = self.request.POST.get('uploaded_file')
file_name = getattr(uploaded_file, 'filename')
file_content = getattr(uploaded_file, 'file')
It will show:
File "C:\Users\pc2\Desktop\test\main.py", line 98, in post
file_name = getattr(uploaded_file, 'filename')
AttributeError: 'unicode' object has no attribute 'filename'
Someone help me to get file or picture ,please!

In your form, you need to an 'enctype' attribute so that uploaded files are handled properly - see this answer for more details on enctype. Your form tag should look like this:
<form action="" method="POST" enctype="multipart/form-data">
Change your post method to this:
def post(self):
uploaded_file = self.request.POST.get('uploaded_file')
file_name = getattr(uploaded_file, 'filename', None)
file_content = getattr(uploaded_file, 'file', None)
if uploaded_file is not None:
self.response.out.write(uploaded_file)
self.response.out.write(file_name)
self.response.out.write(file_content)
The change here is changing if uploaded_file: to if uploaded_file is not None:. This is because a successfully uploaded file will not be None, but would still fail your original if test. I would leave the 'None' arguments to getattr in place - these will prevent exceptions if the user clicks on submit but has not uploaded a file.
Finally, uploaded files do not have a file_content attribute, so this will always be None. If you want to access the file's raw bytes you will need to do
file_content = uploaded_file.file.read()
Note that the file content could be very large, and will not render as an image if you just write it out to the response - you'll just see the raw bytes.

Related

How can I add image file in SQLite database using Flask, Python

I'm writing a small web-shop using Python and web-framework Flask.
I'm trying to add image file in SQLite database using this
#app.route('/new_product_reg', methods=['POST', 'GET'])
def new_product_reg():
if request.method == 'POST':
img_name = request.form['product_img']
product_img = readImage(img_name)
product_img_binary = lite.Binary(product_img)
product_data = NewProduct(product_img=product_img_binary)
try:
db.session.add(product_data)
db.session.commit()
return redirect('/new_product_reg')
except:
return "ERROR!"
Where readImage is
def readImage(img_name):
try:
fin = open(img_name, 'rb')
img = fin.read()
return img
except:
print("ERROR!!")
Form where I taked the image:
<form enctype="multipart/form-data" method="post">
<input type="file" name=product_img id="product_img"><br>
<input type="submit" value="Submit">
</from>
And the class of database where I want to add image looks like that:
class NewProduct(db.Model):
product_img = db.Column(db.BLOB())
def __repr__(self):
return '<NewProduct %r>' % self.id
So, the problem is, when I added image by pressing "Add Image" button in form and pressed "Submit" button I get the BadRequestKeyError 400. The debugger said that the problem is in img_name = request.form['product_img']. So how can I fix that and what I'm doing wrong?
At first I want to say that storing large and medium pictures directly in SQLite is not a very good solution. Learn more here: https://www.sqlite.org/intern-v-extern-blob.html
For your problem, try to do as in the documentation:
https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/
Note there is used:
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
And perhaps this article will also help you:
Python SQLite BLOB to Insert and Retrieve file and images

flask upload CSV file without saving

trying to place my text classification model into flask applications using CSV file upload to read data without saving the uploaded .csv file and throw it into my classifier model print it on the result pages. below example code of my attempt :
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
file.stream.seek(0)
myfile = file.file
dataframe = pd.read_csv(myfile)
return
else:
return "Not Allowed"
return render_template("home.html")
This is my form
<form action="" method=post enctype=multipart/form-data>
<input type=file name="file[]" multiple>
<input type=submit value=Upload>
</form>
exception occurred here
NameError: name 'allowed_file' is not defined
Any idea about this kind of issue ?
I think you are using this part of documentation : (http://flask.pocoo.org/docs/0.12/patterns/fileuploads/)
But you have to add the function :
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS`
Have you created a function called allowed_file() in your module? Or have you created it in another module and forgotten to import it? You’re feeding your filename into the function allowed_file() so that it can check whether the filename is permitted, but the NameError indicates that the function allowed_file() cannot be found.

Copy file into another folder with django?

I need to upload profile images into diferent folders in Django. So, I have a folder for each account, and the profile image have to go to the specific folder. How can I do that?
Here is my uploadprofile.html
<form action="{% url 'uploadimage' %}" enctype="multipart/form-data" method="POST">
{% csrf_token %}
<input type="file" name="avatar" accept="image/gif, image/jpeg, image/png">
<button type="submit">Upload</button>
</form>
And here is my view in views.py
def uploadimage(request):
img = request.FILES['avatar'] #Here I get the file name, THIS WORKS
#Here is where I create the folder to the specified profile using the user id, THIS WORKS TOO
if not os.path.exists('static/profile/' + str(request.session['user_id'])):
os.mkdir('static/profile/' + str(request.session['user_id']))
#Here is where I create the name of the path to save as a VARCHAR field, THIS WORKS TOO
avatar = "../../static/profile/" + str(request.session['user_id']) + "/" + str(img)
#THEN I HAVE TO COPY THE FILE IN img TO THE CREATED FOLDER
return redirect(request, 'myapp/upload.html')
You can pass a callable to upload_to. Basically, what it means is whatever value that callable returns, the image will be uploaded in that path.
Example:
def get_upload_path(instance, filename):
return "%s/%s" % (instance.user.id, filename)
class MyModel:
user = ...
image = models.FileField(upload_to=get_upload_path)
There's more information in the docs and an example too, though similar to what I posted above.
By looking at Django docs what you get when you do img = request.FILES['avatar'] you get a file descriptor that points to an open file with your image.
Then you should to dump the contents in your actual avatar path, right?
#Here is where I create the name of the path to save as a VARCHAR field, THIS WORKS TOO
avatar = "../../static/profile/" + str(request.session['user_id']) + "/" + str(img)
# # # # #
with open(avatar, 'wb') as actual_file:
actual_file.write(img.read())
# # # # #
return redirect(request, 'myapp/upload.html')
Beware: the code is untested.
from django.shortcuts import render
from django.conf import settings
from django.core.files.storage import FileSystemStorage
def uploadimage(request):
if request.method == 'POST' and request.FILES['avatar']:
img = request.FILES['avatar']
fs = FileSystemStorage()
#To copy image to the base folder
#filename = fs.save(img.name, img)
#To save in a specified folder
filename = fs.save('static/profile/'+img.name, img)
uploaded_file_url = fs.url(filename) #To get the file`s url
return render(request, 'myapp/upload.html', {
'uploaded_file_url': uploaded_file_url
})
return render(request, 'myapp/upload.html')

How to upload file in python webapp2?

I am using python webapp2 (Python framework) and google app engine for my project, i want to upload files to my project directory just like move_upload_files in php
Thanks
You can upload files to the blobstore using webapp2. You first must create the upload url when dispatching to your upload form:
self.render('upload-ui.html', {
...
'form_url': blobstore.create_upload_url('/upload_form'),
})
Then in your upload form you use the form_url
<form method="post" action="{{ form_url }}" name="formular" class="ui form" accept-charset="UTF-8"
enctype="multipart/form-data">
The uploaded files are available from self.get_uploads in the post method of your code:
for upload in self.get_uploads():
try:
content_type = blobstore.blobstore.BlobInfo(upload.key()).content_type
if 'video' in content_type:
vid = Video(reference=user)
vid.content = upload.key()
vid.title = blobstore.blobstore.BlobInfo(upload.key()).filename
vid.size = blobstore.blobstore.BlobInfo(upload.key()).size
vid.put()
except Exception, e:
logging.error('There was an exception:%s' % str(e.message))
pass

Django download a file

I'm quite new to using Django and I am trying to develop a website where the user is able to upload a number of excel files, these files are then stored in a media folder Webproject/project/media.
def upload(request):
if request.POST:
form = FileForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return render_to_response('project/upload_successful.html')
else:
form = FileForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('project/create.html', args)
The document is then displayed in a list along with any other document they have uploaded, which you can click into and it will displays basic info about them and the name of the excelfile they have uploaded. From here I want to be able to download the same excel file again using the link:
Download Document
My urls are
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Post.objects.all().order_by("-date")[:25],
template_name="project/project.html")),
url(r'^(?P<pk>\d+)$', DetailView.as_view(model=Post, template_name="project/post.html")),
url(r'^upload/$', upload),
url(r'^download/(?P<path>.*)$', serve, {'document root': settings.MEDIA_ROOT}),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
but I get the error, serve() got an unexpected keyword argument 'document root'. can anyone explain how to fix this?
OR
Explain how I can get the uploaded files to to be selected and served using
def download(request):
file_name = #get the filename of desired excel file
path_to_file = #get the path of desired excel file
response = HttpResponse(mimetype='application/force-download')
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
return response
You missed underscore in argument document_root. But it's bad idea to use serve in production. Use something like this instead:
import os
from django.conf import settings
from django.http import HttpResponse, Http404
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
You can add "download" attribute inside your tag to download files.
<a href="/project/download" download> Download Document </a>
https://www.w3schools.com/tags/att_a_download.asp
Reference:
In view.py Implement function like,
def download(request, id):
obj = your_model_name.objects.get(id=id)
filename = obj.model_attribute_name.path
response = FileResponse(open(filename, 'rb'))
return response
When you upload a file using FileField, the file will have a URL that you can use to point to the file and use HTML download attribute to download that file you can simply do this.
models.py
The model.py looks like this
class CsvFile(models.Model):
csv_file = models.FileField(upload_to='documents')
views.py
#csv upload
class CsvUploadView(generic.CreateView):
model = CsvFile
fields = ['csv_file']
template_name = 'upload.html'
#csv download
class CsvDownloadView(generic.ListView):
model = CsvFile
fields = ['csv_file']
template_name = 'download.html'
Then in your templates.
#Upload template
upload.html
<div class="container">
<form action="#" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button class="btn btn-primary btn-sm" type="submit">Upload</button>
</form>
#download template
download.html
{% for document in object_list %}
Download
{% endfor %}
I did not use forms, just rendered model but either way, FileField is there and it will work the same.
I've found Django's FileField to be really helpful for letting users upload and download files. The Django documentation has a section on managing files. You can store some information about the file in a table, along with a FileField that points to the file itself. Then you can list the available files by searching the table.
#Biswadp's solution worked greatly for me
In your static folder, make sure to have the desired files you would like the user to download
In your HTML template, your code should look like this :
Download
Using the below approach makes everything less secure since any user can access any user's file.
<a href="/project/download" download> Download Document </a>
Using the below approach makes no sense since Django only handles one requests at the time (unless you are using gunicorn or something else), and believe me, the below approach takes a lot of time to complete.
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
So what is the optimum solution?
Use Nginx authenticated routes. When requesting a file from Nginx you can make a request to a route and depending on the HTTP response Nginx allows to denies that request. This makes it very secure and also scalable and performant.
You can ready about more here
import mimetypes
from django.http import HttpResponse, Http404
mime_type, _ = mimetypes.guess_type(json_file_path)
if os.path.exists(json_file_path):
with open(json_file_path, 'r') as fh:
response = HttpResponse(fh, content_type=mime_type)
response['Content-Disposition'] = "attachment; filename=%s" % 'config.json'
return response
raise Http404
<a href='/your-download-view/' download>Download</a>
In your view:
from django.http import FileResponse
def download(request):
# pre-processing, authorizations, etc.
# ...
return FileResponse(open(path_to_file, 'rb'), as_attachment=True)
Simple using html like this downloads the file mentioned using static keyword
Download CV
1.settings.py:
MEDIA_DIR = os.path.join(BASE_DIR,'media')
#Media
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'
2.urls.py:
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
3.in template:
<a href="{{ file.url }}" download>Download File.</a>
Work and test in django >=3
for more detail use this link:
https://youtu.be/MpDZ34mEJ5Y
If the file is a FileField in the model, this is the way I do it:
try:
download_file = PrintingFile.objects.get(pk=kwargs.get('pk_file', 0))
return FileResponse(download_file.file.open(), as_attachment=True)
except PrintingFile.DoesNotExist:
raise Http404
More here
I use this method:
{% if quote.myfile %}
<div class="">
<a role="button"
href="{{ quote.myfile.url }}"
download="{{ quote.myfile.url }}"
class="btn btn-light text-dark ml-0">
Download attachment
</a>
</div>
{% endif %}
If you hafe upload your file in media than:
media
example-input-file.txt
views.py
def download_csv(request):
file_path = os.path.join(settings.MEDIA_ROOT, 'example-input-file.txt')
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
urls.py
path('download_csv/', views.download_csv, name='download_csv'),
download.html
a href="{% url 'download_csv' %}" download=""

Categories

Resources