Fastapi Upload a Image - python

i try to upload a image to a fastapi from a Cordova Webapp and get the following error:
{"detail":[{"loc":["body","terms"],"msg":"field required","type":"value_error.missing"},{"loc":["body","privacy"],"msg":"field required","type":"value_error.missing"}]}
INFO: 192.168.1.129:51915 - "POST /upload/ HTTP/1.1" 422 Unprocessable Entity
My FastApi Code is:
#app.post("/upload/", dependencies=[Depends(valid_content_length)])
async def create_upload_file(file: bytes = File(...), terms: str = Form(...), privacy: str = Form(...)):
allowedFiles = {"image/jpeg", "image/png", "image/gif", "image/tiff", "image/bmp", "video/webm"}
if file.content_type in allowedFiles:
filename = str(uuid.uuid4())
with open("uploaded_images" + filename + file.filename, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {"filename": file.filename}
else:
return "miau"
Client Code:
<form method="post" action="http://192.168.1.129:8080/upload">
<div class="form_row">
<label for="myfile">Choose your image:</label>
<input type="file" id="myfile" name="file">
</div>
<div class="form_row">
<label>Accept:</label>
<label class="label-checkbox item-content">
<input type="checkbox" name="my-checkbox" value="privacy" required>
<div class="item-media">
<i class="icon icon-form-checkbox"></i>
</div>
<div class="item-inner">
<div class="item-title"><a src="" target="_blank">Privacy Policy</a></div>
</div>
</label>
<label class="label-checkbox item-content">
<input type="checkbox" name="my-checkbox" value="terms" required>
<div class="item-media">
<i class="icon icon-form-checkbox"></i>
</div>
<div class="item-inner">
<div class="item-title">Terms of Use</div>
</div>
</label>
<label class="label-checkbox item-content">
<input type="submit" name="submit" class="form_submit" id="submit" value="Send"/>
</label>
</div>
</form>
How to solve the problem? According to error the body is empty, but I don't know what the problem is.
Thanks :)

The error says pretty much everything
"loc":["body","terms"],"msg":"field required"
and
"loc":["body","privacy"],"msg":"field required"
This means that your form is not submitting the terms and the privacy fields.
If you look at your HTML code, you can see that both of the inputs have the name my-checkbox, while fastapi route expects two parameters: privacy and terms.
Change the names of the inputs to match the two parameters

Related

How to login to a website using python and upload a file to s3?

I have a script that uploads a file from a public URL to S3 which is working fine. i have a need to use this script to upload some files which are not Public, i need to log in to the site to get the file. i need help implementing this in my script; where the script would log in to the site and get the file. site i am trying to login to https://catalog.ldc.upenn.edu/login
Here is my Script
import threading
import requests
import boto3
from boto3.s3.transfer import TransferConfig
def multi_part_upload_with_s3():
config = TransferConfig(multipart_threshold=1024 * 25, max_concurrency=30,
multipart_chunksize=1024 * 25, use_threads=True)
url = "www.example-url.com"
r = requests.get(url, stream=True)
session = boto3.Session()
s3 = session.resource('s3')
key = 'examplePath/file'
bucket = s3.Bucket(bucket_name)
bucket.upload_fileobj(r.raw, key, Config=config, Callback=None)
Here is the html from the site i need to log in to
<form class="new_spree_user" id="new_spree_user" action="/login" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="xjxGqf8OYqJd6Ynt1GcK1Ms0XM6YcPz3kS69TFKCCRQwOgwh1kEMlpJSTKAoblXLtLpSLCIiwPWT+LLab0Altw==">
<div id="password-credentials">
<p>
<label for="spree_user_email">E-mail</label><br>
<input class="title" tabindex="1" type="text" name="spree_user[login]" id="spree_user_login">
</p>
<p>
<label for="spree_user_password">Password</label><br>
<input class="title" tabindex="2" type="password" name="spree_user[password]" id="spree_user_password">
</p>
</div>
<p>
<input name="spree_user[remember_me]" type="hidden" value="0"><input type="checkbox" value="1" name="spree_user[remember_me]" id="spree_user_remember_me">
<label for="spree_user_remember_me">Remember me</label>
</p>
<p><input type="submit" name="commit" value="Login" class="button primary" tabindex="3" id="submit_form" data-disable-with="Login"></p>
</form>
or
Create a new account |
Forgot password?

How can I ask user to upload image to an html page, insert this image to an sqlite3 table using flask, and then display this image using jinja?

so far this is what I came up with
#html ask user to input information including an image
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="name" placeholder="name" type="text">
</div>
<div class="form-group">
<input class="form-control" name="subject" placeholder="subject" type="text">
</div>
<div class="form-group">
<input class="form-control" name="experience" placeholder="experience" type="text">
</div>
<div class="form-group">
<input class="form-control" name="phone" placeholder="puone-number" type="number">
</div>
<div class="form-group">
<input type="file" name="pic" id="pic">
</div>
<button class="btn btn-primary" type="submit">Register</button>
</form>
flask
#app.route("/register", methods=["GET", "POST"])
def register():
"""Show teacher registering menu"""
if request.method == "GET":
return render_template("register.html")
else:
# get the user input
name = request.form.get("name")
sub = request.form.get("subject")
exp = request.form.get("experience")
phone = request.form.get("phone")
f = request.files['pic']
pic = f.save(secure_filename(f.filename))
if not name or not sub or not exp or not phone:
return "404"
# insert in the database
sql = "INSERT INTO teachers (name, sub, exp, phone, pic) VALUES (?, ?, ?, ?, ?)"
db.execute(sql, name, sub, exp, phone, pic)
# inform the user for the success of the process
return render_template("success.html")
showing the results on html
<div>
{% for i in query %}
<div class="media bg-primary text-white">
<img class="align-self-end mr-3" src={{ i['pic'] }} alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0">Mr. {{ i['name'] }}</h5>
<ul class="list-group list-group-flush text-dark">
<li class="list-group-item">subject: {{ i['sub'] }},</li>
<li class="list-group-item">experience: {{ i['exp'] }},</li>
<li class="list-group-item">Contact number: {{ i['phone'] }}</li>
</ul>
</div>
</div>
<br>
{% endfor %}
</div>
but right now every time I try it I find the value of the image column in my sql table to be NULL.
How can I fix that
pic = f.save(secure_filename(f.filename))
The save method returns None, so here pic will be None.
I think you intended to write its filename to the database, so perhaps change this to:
pic = secure_filename(f.filename)
f.save(pic)
Now pic is the filename on your server, so you just need to reconstruct this wherever the file is viewed.
Of course be aware that this uses the filename of the file which was uploaded by the user. You may wish to avoid this, incase of duplicates or just for cleanliness. See this other answer I wrote regarding that.
EDIT: Regarding your template.
When it comes to loading the picture in the template, let's assume the filename came through as image.jpg, and you use your exisiting code:
<img src={{ i['pic'] }}>
You could view the source of the rendered page, and see:
<img src=image.jpg>
Two problems with this:
that attribute should have quotes (<img src="image.jpg">)
that's trying to load the file from whichever path is rendered in the browser, so if the URL was http://example.com/subdir/ it's looking for the image at http://example.com/subdir/image.jpg. This can also be verified in the Network tab of your browsers dev tools.
The solution, build the URL with flask's url_for function:
<img src="{{ url_for('static', filename=i['pic']) }}">
This, of course, assumes that you've saved the file to the static directory on your server. You may wish to ensure this in the python code:
import os
# ...
pic = secure_filename(f.filename)
f.save(os.path.join('static', pic))

Click button with Python and requests

I need their help with a requests call for click a button with python and request.
The HTML code the form is this:
<form action="someurl/changedata" enctype="multipart/form-data" method="POST">
<p class="message">
Description
</p>
<div class="data-field-grouping" data-field-grouping-name="Passwords">
<div class="data-field" data-field-name="OldPassword">
<label data-required="data-required" for="OldPassword">Old Password</label><input id="OldPassword" maxLength="128" name="OldPassword" required="required" type="password" /></div>
<div class="data-field" data-field-name="Password">
<label data-required="data-required" for="Password">New Password</label><input id="Password" maxLength="128" name="Password" required="required" type="password" /></div>
<div class="data-field" data-field-name="PasswordConfirmation">
<label data-required="data-required" for="PasswordConfirmation">Confirm Password</label><input id="PasswordConfirmation" maxLength="128" name="PasswordConfirmation" required="required" type="password" /></div>
</div>
<input name="__RequestVerificationToken" type="hidden" value="xwvDA9Y-bzAY4Z9F3UVSnuFlYEuVfD2F8kYY4aD__wKzjQct7y6JZ4Jd6_YpxhQIXq0zcRJ-RfLxleHgT49P-lMecIB55LEyXCMylaTxK1KzI_HqbWM101FGmaK33Y2z0" /><button type="submit">Change Password</button></form>
I’ve been trying with this code and the login works successfully but the next part not, well. It doesn’t gives me error, but just gives me the html of the body.
import requests
from requests_ntlm import HttpNtlmAuth
info = {'OldPassword':'firstpass',
'Password':newpass,
'PasswordConfirmation': newpass,
'__RequestVerificationToken':'0'
}
s = requests.session()
with requests.session() as s:
responsee = s.get("url",auth=HttpNtlmAuth('username', 'firstpass'))
print (responsee.text)
if responsee.status_code == 200:
print("Login successfully")
response = s.post("url2",params=info)
print(response.text)

Flask mail api, not getting request variable properly

I'm trying to access a request from an HTML form, and send it as a mail, but I get a mail with a value of "None",
here is my code:
#app.route("/about", methods=['GET', 'POST'])
def send_message():
name = request.form.get('name')
msg = Message(
subject='Hello ' + str(name),
sender='kristofferlocktolboll#gmail.com',
recipients=
['kristofferlocktolboll#gmail.com'],
html=render_template("about.html"))
mail.send(msg)
confirm_msg = "Your message has been sent!"
return render_template("about.html", confirm_msg=confirm_msg)
I think it might be due to the fact, that I'm casting the object into a string, but if I don't do that, I will get an error due to making a conjunction between a String and another object
EDIT:
here is my html code, I have tried both using post and get as the method, but nothing works.
<form action="/send_message" method="post">
First name: <br>
<input type="text" name="name" size="35"><br>
Last name:<br>
<input type="text" name="lastname" size="35"><br>
Email-address: <br>
<input type="email" name="email" size="35"><br>
Phone-number: <br>
<input type="text" name="phone" size="35"><br>
Enter your message: <br>
<textarea type="text" name="message" rows="7" cols="40"></textarea><br>
</form>
EDIT 2:
When ever I try to display the confirm_msg it is displayed instantly, when I enter the site.
<p>{{confirm_msg}}</p>
Firstly you must add CSRF_TOKEN for your form:
<form method="post" action="/send_message">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
...
.....
</form>
Also can you tell us in which page you are trying to see <p>{{confirm_msg}}</p> ?

400 Bad Request (Flask + html)

I keep getting a 400 Bad Request when I try to run my Flask project.
I have to do a project using Flask and HTML, and it was supposed to be a group project, so members would have to learn different parts of it to then gather everything. Sadly, my 'group' didn't do anything at all
Here's my code:
Flask
app = Flask(__name__, static_url_path="")
#app.route('/', methods=['POST','GET' ]) #1 - Login e criar conta
def PagInicio():
button = request.form["button"]
if request.method == 'POST':
if button == "login":
return render_template("Princ.html")
elif button =="criar":
return render_template("Criar.html")
else:
return render_template("Inicio.html")
return render_template("Inicio.html")
HTML:
<div class="col_12">
</div>
<!-- Tab 3 - Perfil -->
<div id="tabr3" class="tab-content">
<div class="grid">
<div class="col_2"></div>
<div class="col_8">
<form class="vertical" method="POST" action="/">
<fieldset>
<div class="grid">
<div class="col_6">
<label for="usuario">Usuário</label>
<input id="usuario" name="usuario" type="text" />
</div>
<div class="col_6">
<label for="senha">Senha</label>
<input id="senha" name="senha" type="password" />
</div>
<div class="col_12 center">
<button class="medium" value="login"</i> Login</button>
</div>
<div class="col_12 center">
<button class="medium" value="criar"</i> Criar</button>
</div>
</form>
</div>
<div class="col_2"></div>
</div>
</div>
</div>
<div class="col_1"></div>
</div>
You are trying to access the request.form dictionary, always:
button = request.form["button"]
This throws a 400 response error if there is no such value in the form. This is always the case when you have a GET request, request.form is only populated when there is POST data in a valid format.
Only try to access the button when you already confirmed you have a POST request:
def PagInicio():
if request.method == 'POST':
button = request.form["button"]
if button == "login":
return render_template("Princ.html")
elif button =="criar":
return render_template("Criar.html")
else:
return render_template("Inicio.html")
return render_template("Inicio.html")
Next, you don't actually have any form element named button. You have button form elements but none have a name. Give all your buttons the same name attribute, varying the value attribute:
<div class="col_12 center">
<button class="medium" name="button" value="login"> Login</button>
</div>
<div class="col_12 center">
<button class="medium" name="button" value="criar"> Criar</button>
</div>
Note that you malformed the <button tags too.

Categories