here is my code to upload images to folder and name to the database and it isn't working.
i am getting an error 'bytes' object has no attribute 'image' Exception occured
#html code -->#
<html>
<head>
<TITLE> Product Image</TITLE>
</head>
<body>
<form enctype="multipart/form-data" action="productimg.py" method=post>
<table align=center cellspacing=20 cellpadding=10 >
<th align="center" colspan=3 > <u>Upload Image of the Goods</u></th>
<tr ><th colspan="4"> Enter your details below and wait minimum for half an hour.</th></tr>
<tr>
<td> Product Image : </td><td> <input type=file name="image" accept = "image/*" accept=".png/*" value="image"> </td>
</tr>
<tr>
<td> </td> <td> <input type=Submit > <input type=Reset> </td>
</tr>
</table>
</form>
</body>
</html>
i am getting an error 'bytes' object has no attribute 'image' Exception occured in pyhton code.
#python code -->#
#!C:\Users\Pc\AppData\Local\Programs\Python\Python38-32\python.exe
print('Content-type:text/html\n\r')
import cgi
import sys
from myconnect import *
message=0
try:
con,cur=myconnect()
form= cgi.FieldStorage()
# Get here.
fileitem=form.getvalue('image');
#fileitem = form['image']
# Test if the file was uploaded
if fileitem.image:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.image)
open('/uploads/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
query=f"select product_delivery_id from tbl_product_deliver order by product_delivery_id desc"
cur.execute(query)
pid=cur.fetchone()
update=f"UPDATE `tbl_product_deliver` SET `product_image`='{fn}' WHERE `product_delivery_id`='{pid}'"
cur.execute(update)
con.commit()
else:
message = 'No file was uploaded'
except Exception as e:
print(e)
print("Exception occured")
You cannot use a python script like php. Typically you have to configure an eventhandler waiting for a post-request. For doing this in python you need a framework like flask or bottle for receiving post request and instead of productimg.py you use the route you've set with this framework as action in html.
Your FieldStorage object is called without arguments, so you create an empty Fieldstorge object with no data.
A FieldStorage object receiving a post request looks like this:
fs= FieldStorage(fp=request.body, headers=request.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':request.headers['Content-Type'], })
However ensure you solved issue 1 before doing issue 2.
With bottle use this python code:
from bottle import post, request, run
#post('/upload')
def getImage():
#printing the raw data
print(request.body)
#insert your code here
run(host='localhost', port=8080)
and change in html:
action="http://localhost:8080/upload
Good luck
Related
i created a little web app that allows to upload and download files (pdf,txt,docx) to a sqlite3 database. I use flask as backend framework. When i hit the download button the download route gets called and everything seems fine but the download tab of the browser is not opening and nothing gets downloaed.
The print statement logs a valid filename to the terminal. Where did i go wrong ?
html snippet for upload and download :
{% block main %}
<div class="grid-item">
<h4>Datenbank</h4>
<table style="display: flex;justify-content: space-evenly;">
<tr >
<td>
download
</td>
<td>
Datei
</td>
<td>
löschen
</td>
</tr>
{% for file in current_user.files %}
<tr>
<td>
<button type="button" class="close" onClick="download_files({{ file.id }})">
<i class="bi bi-box-arrow-down" style="color: black;"></i>
</button>
</td>
<td>
<li class="list-group-item">
{{ file.filename }}
</li>
</td>
<td >
<button type="button" class="close" onClick="delete_files({{ file.id }})" >
<span aria-hidden="true" style="color:black">×</span>
</button>
</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
{% endblock%}
javascript used:
function download_files(fileid) {
fetch("/download", {
method: "POST",
body: JSON.stringify({ fileid: fileid }),
})
}
flask code:
#files.route("/download" , methods=["POST"])
#login_required
def download():
file = json.loads(request.data)
fileID = file["fileid"]
file = Upload.query.filter_by(id=fileID).first()
if file:
if file.user_id == current_user.id:
print(f"file {file.filename} downloaded !" )
return send_file(BytesIO(file.data), download_name=file.filename,as_attachment=True )
EDITE 1 :
Upload code
html:
<div class="grid-item">
<h4>Datei hochladen</h4>
<h5>Unterstütze Dateiformate: .doc .docx .pdf .txt .odt</h5>
<form action="{{ url_for('files.upload') }}" id="dropzone" class="dropzone" multiple accept=".doc,.docx,.pdf,.txt,.odt">
</form>
</div>
python:
#files.route("/upload", methods=["GET", "POST"])
#login_required
def upload():
if request.method == 'POST':
allowed_files = [".doc",".docx",".pdf",".txt",".odt"]
file = request.files['file']
file_ext = os.path.splitext(file.filename)[1]
if file_ext not in allowed_files:
flash(f"Dateiformat {file_ext} nicht unterstütt! ",category="error")
return render_template("drive.html")
elif not file.filename == '':
upload = Upload(filename=secure_filename(file.filename), data=file.read(),date=datetime.datetime.now(),user_id=current_user.id)
db.session.add(upload)
db.session.commit()
flash(f"Dateien hochgeladen ! ",category="sucess")
return redirect(url_for("views.drive"))
else:
flash(f"Ungültiger Dateiname Dateiname: {file.filename} ! ",category="error")
return render_template("drive.html")
else:
return render_template("drive.html")
I did check that the correct file gets submited to the download function. Also that the file exists and that the funcion runs till the return statement.
I checked the flask send_file documentation for mistakes of the send_file() function and checked the dev tools of chrome to see if there is a payload.
EDIT 2:
I did try it with the following code which works. Maybe someone can explain the difference to me. From my consol logs my code does exactly the same, just gets the id through javascript fetch() and not by a flask route credential.
#app.route('/download/<upload_id>')
def download(upload_id):
upload = Upload.query.filter_by(id=upload_id).first()
return send_file(BytesIO(upload.data), download_name=upload.filename, as_attachment=True)
The reason why i dont use this is, because i dont know how to send the file id to the flask route without a javascript part. Maybe someone can help me on that part.
This question already has answers here:
Get the data received in a Flask request
(23 answers)
Closed 8 months ago.
I'm very new to using Flask and I'm trying to make a simple script to visualize the data I have stored in my database (basically a bunch of products, categories and some other things, all from vending machines), I did the main menu page and the 'categorias' (category) page, where I'm able to see all the categories (of products) in my system, and since categories can have sub-categories I made another page where I can see all the 'sub_categorias' (sub-categories) of the category I want.
For this I made a link from my 'categorias.html' file to 'categorias/sub_categorias?nome={{ record[0] }}', ('nome' being name in my language, and being the name of the "super category" of this sub-category), like so:
Sub categorias
and it works fine, linking to a new page where the form "nome" is correct, like so:
but as you can see I get a Bad request error, that I think happens because in my python code, when I do request.form["nome"] it for some reason doesn't get anything, when it should get Sopa. Here's my code:
# Show all the sub-categories of a catgory.
#app.route("/categorias/sub_categorias")
def show_sub_categories():
dbConn = None
cursor = None
try:
dbConn = psycopg2.connect(DB_CONNECTION_STRING)
cursor = dbConn.cursor(cursor_factory = psycopg2.extras.DictCursor)
# Gets all the sub-categories of the super category given.
query = "SELECT categoria FROM tem_outra WHERE super_categoria=%s;"
# Gets the data we need from the URL query string.
data = (request.form["nome"])
cursor.execute(query, data)
return render_template("sub_categorias.html", cursor = cursor, params = request.args)
except Exception as e:
return str(e)
finally:
cursor.close()
dbConn.close()
For extra context here's my 'categorias.html' file body (although I'm almost certain the problem comes from here):
<h1> Categorias </h1>
<div id="table">
<button onclick="window.location.href='menu'"> Menu principal </button>
<button onclick="window.location.href='categorias/inserir_categoria'"> Inserir categoria </button>
<button onclick="window.location.href='categorias/remover_categoria'"> Remover categoria </button>
<table id="Category_table">
<thead>
<tr>
<th> Nome </th>
<th> Gerir </th>
</tr>
</thead>
<!-- For loop to fetch all the system's categories. -->
{% for record in cursor %}
<tr>
<td> {{ record[0] }} </td>
<td>
Sub categorias
</td>
</tr>
{% endfor %}
</table>
</div>
I really don't know what I'm doing wrong, so if someone could help me I'd very much appreciate it, Thanks.
When you want to obtain the value of a GET request, you need to do:
nome = request.args.get('nome')
You use request.form when process a POST request
I have a script that gets a table from MSSQL database and then registers it with ArcGIS. It uses several other arcpy methods as well. I tried to combine it with Flask and developed an HTML interface where you can specify tables. The script runs on console perfectly well, however, when running with Flask on http://127.0.0.1:5000/ , the arcpy functions do not run, then the app throws errors.
I am using my local python directory, so I do not have any problem with importing arcpy on flask. So, I am able to use pymssql functions and create a new table, however when it comes to arcpy function, It throws does not exist error, however, the table exists. I feel like there is something wrong with running arcpy with Flask, but any help would be appreciated.
(2) I tried the same thing in Django but I am having the same problem.
Thanks
forms.py
class createGISLayer(FlaskForm):
tCreateLayer = SubmitField('Create GIS Layer')
DashboardMain()
try:
cursor.execute(QueryCreate)
print ("Table Created.")
print(self.dbTablePath)
descTable = arcpy.Describe(self.dbTablePath)
except arcpy.ExecuteError:
print(arcpy.GetMessages())
app.py
if formCreate.tCreateLayer.data and formCreate.validate_on_submit():
if myLayer is not None:
try:
print("Create GIS Layer")
myLayer.dashboardMain()
flash('GIS Layer created!', 'success')
except Exception as e:
print(e.message)
flash(e.message, 'danger')
index.html
<!-- Create GIS Layer -->
<div class="content-section">
<form name='idCreateGISLayer' action="" method="POST">
<table style="height: auto; margin-left: auto; margin-right: auto; width: 600px;">
<tbody>
<tr>
{{ formCreate.hidden_tag() }}
<td style="height: 39px; width: 259px">
<h2 style="text-align: left;"><font size="3"><strong>(2) Create </strong></font></h2>
</td>
<td style="text-align: left; height: 39px;">
<div class="auto-style2">
{{ formCreate.tCreateLayer(class="btn btn-outline-info")}}
</div>
</td>
</tr>
</tbody>
</table>
</form>
</div>
ERROR
Table Created.
F:\Projects\Dashboard\Publish.sde\Publish.dbo.A_WebT1
"F:\Projects\Dashboard\Publish.sde\Publish.dbo.A_WebT1" does not exist
screenshot
Instead of calling the function, I ran my script with DOS.
#app.route('/cad2json', methods=['POST'])
def cad2sde():
dwg_path = request.form.get('dwg_path')
reference_scale = request.form.get('reference_scale')
spatial_reference = request.form.get('spatial_reference')
target_layer = request.form.get('target_layer')
sentence = (u'C:\\Python27\\ArcGIS10.1\\python.exe C:\\Users\\Administrator \\Desktop\\flask\\cad.py %s %s %s %s'
%(dwg_path,reference_scale,spatial_reference,target_layer))
p = os.popen(sentence)
return format(p.read())
ArcPy is not free. It only works in ESRI software or anaconda. You can not import.
I execute my script in command line.
When I execute ./script.py server_adress param2 param3 param4 it opens a page with html form and a button, when we type on the button, I want to retrieve this server address.
that's a part of the code of the script.py :
import os, sys, platform, getpass, tempfile
import webbrowser
import string
import json
def main( server_IP, code_name, code_version, install_path):
template = open('scriptHmtl.phtml').read()
contenu = string.Template(template).substitute(
code_name = code_name,
code_version = code_version,
install_path = install_path,
os = user_os,
user_name = user_login
)
f = tempfile.NamedTemporaryFile(prefix='/tmp/info.html', mode='w', delete=False)
f.write(contenu)
f.close()
webbrowser.open(f.name)
if __name__ == "__main__":
server_IP = sys.argv[1]
code_name = sys.argv[2]
code_version = sys.argv[3]
install_path = sys.argv[4]
user_os = sys.platform
sys.argv.append(user_os)
user_login = getpass.getuser()
sys.argv.append(user_login)
config_file = open("config.txt", "w")
json.dump(sys.argv, config_file)
main(server_IP, code_name, code_version, install_path)
and here, the code html to get the address , scriptHtml.py
<html>
<body>
App: ${code_name}<br/><br/>
cv: ${code_version}<br/><br/>
path install: ${install_path}<br/><br/>
<form name="Data" method="get" action="http://localhost:8000/cgi/scriptGet.py">
Name: <input type="text" name="name"><br/><br/>
First name: <input type="text" name="fn"/><br/><br/>
Mail: <input type="text" name="mail"/><br/><br/>
<input type="submit" value="OK"/>
</form>
</body>
</html>
action="http://localhost:8000/cgi/scriptGet.py" -> I think the problem is here.
What you really want to do here is use a proper Python Web Framework.
CGI went out of fasion decdaes ago?
Example: (Using circuits):
#!/usr/bin/env python
"""Forms
A simple example showing how to deal with data forms.
"""
from circuits.web import Server, Controller
FORM = """
<html>
<head>
<title>Basic Form Handling</title>
</head>
<body>
<h1>Basic Form Handling</h1>
<p>
Example of using
circuits and its
<b>Web Components</b> to build a simple web application that handles
some basic form data.
</p>
<form action="/save" method="POST">
<table border="0" rules="none">
<tr>
<td>First Name:</td>
<td><input type="text" name="firstName"></td>
</tr>
<tr>
<td>Last Name:</td>
<td><input type="text" name="lastName"></td>
</tr>
<tr>
<td colspan=2">
<input type="submit" value="Save">
</td>
</tr>
</table>
</form>
</body>
</html>"""
class Root(Controller):
def index(self):
"""Request Handler
Our index request handler which simply returns a response containing
the contents of our form to display.
"""
return FORM
def save(self, firstName, lastName):
"""Save Request Handler
Our /save request handler (which our form above points to).
This handler accepts the same arguments as the fields in the
form either as positional arguments or keyword arguments.
We will use the date to pretend we've saved the data and
tell the user what was saved.
"""
return "Data Saved. firstName={0:s} lastName={1:s}".format(
firstName, lastName
)
app = Server(("0.0.0.0", 8000))
Root().register(app)
app.run()
Disclaimer: I'm the developer of circuits.
NB: There are many other good Python Web Frameworks:
flask
bottle
Django
... etc ...
contenu = string.Template(template).substitute(
code_name = code_name,
code_version = code_version,
install_path = install_path,
os = user_os,
user_name = user_login
server_IP = http:8000/cgi/scriptGet.py
)
scriptHtml.py
<form name="Data" method="get" action="${server_IP}">
that is something like that ?
I can't get this to work: I navigate to the page I want, but I'm doing something wrong with the variables it seems.
views.py:
#view_config(http_cache=1,route_name='hoofdpagina', renderer='templates/hoofdpagina.pt')
def hoofdpagina(request):
page = DBSession.query(MyModel) #.filter_by(id='1').all()
if 'form.submitted' in request.params:
name= request.params['name']
page2=Page(name)
DBSession.add(page2)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return dict(page=page)
#view_config(route_name='diagnose', renderer='templates/diagnose.pt')
def diagnose(request):
return request
kak = ['test1','test2','test3t']
content = {"test1","test2","test3"}
return {'content' :content, 'test' :kak}
hoofdpagina.pt:
<form class="span12" action="/diagnose" method="POST">
<table class="table table-hover">
<thead class="header">
<tr>
<th>D Nr.</th>
<th>Datum</th>
<th>Patient</th>
<th>Prior</th>
</tr>
</thead>
<tr tal:repeat="Page page" >
<td tal:content="Page.dosiernummer"></td>
<td tal:content="Page.dosiernummer"></td>
<td tal:content="Page.datum"></td>
<td tal:content="Page.naamPatient"></td>
<td tal:content="Page.prioriteit"></td>
</tr>
</table>
</form>
<form action="/diagnose" method="post">
<input type="submit" value="Save" name="form.submitted" ></input>
<label name="name">et werkt slet</label>
</form>
I can show all the variables of page in my table. But when I press the submit button I can't get the content of the "name" label to my diagnose page. I don't know how I can show the value.
ps: question is based on this post: Pyramid app: How can I pass values into my request.route_url?
Instead of you'd need an input of some sort:
<input type="text" name="name" value="et werkt slet">
or type="hidden" if you don't want it displayed.
I'm still learning Pyramid as well, but I also wonder if from your code that the submit action is going to post to def hoofdpagina anyway. I think you might have to move your POST handling to:
#view_config(route_name='diagnose', renderer='templates/diagnose.pt')
def diagnose(request):
if 'form.submitted' in request.params:
name= request.params['name']
page2=Page(name)
DBSession.add(page2)
return HTTPFound(location=request.route_url('view_page',pagename=name))
a sollution is working with url dispatching like this:
_init_.py:
config.add_route('diagnose1', '/diagnose1/{dosierid}')
views.py
#view_config(route_name='diagnose1', renderer='templates/diagnose.pt')
def diagnose1(request):
tabeldata=''
dosierid = request.matchdict['dosierid']
now you have your id from one view to another.
In the init.py you have to add url dispatching (config.add_route).
Your can get the data out of the url and pass on to another page like this.