Upload base64 image to couchdb - python

Im Trying to Upload a base64 image which I got from doing canvas.toDataUrl();
but nothing happens when I try and do a put request to couchdb. Im not sure how to retrieve the response to see if it worked.
Here is my request:
#app.route('/process', methods=['POST'])
def process():
email = request.form['email']
name = request.form['name'],
file = request.form['data'] #'data' is from html and was var srcdata = canvas.toDataURL()
if file:
print(file)
j = {"_id": "ab","_attachments":{"aboutme.jpg":{"content_type":"image/png","data":file}}}
requests.put('http://127.0.0.1:5984/test2/',data=None,json=j)
EDIT
the string that is in the data value in the jj json works and allows me to upload and attachment to couchdb but when I pass it the file that doesnt work. Im thinking it doesnt because its not a proper base64, I think it could actually be a domString.
#app.route('/process', methods=['POST'])
def process():
email = request.form['email']
name = request.form['name'],
file = request.form['data']
if file:
print(file)
jj = {
"_attachments":
{
"aboutme.png":
{
"content_type": "image/png",
"data":"VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
}
}
}
requests.post('http://127.0.0.1:5984/test2/', data=None, json=jj)
return jsonify({'name': "yes"})

Related

Uploading images get corrupted but not txt files

I am trying to upload an image using AWS lambdas but my images get corrupted I tested with a txt file and it works great. The function checkImage is the handler
def parse_into_field_storage(fp, ctype, clength):
fs = FieldStorage(
fp=fp,
environ={'REQUEST_METHOD': 'POST'},
headers={
'content-type': ctype,
'content-length': clength
},
keep_blank_values=True
)
form = {}
files = {}
for f in fs.list:
if f.filename:
files.setdefault(f.name, []).append(f)
else:
form.setdefault(f.name, []).append(f.value)
return form, files
def checkImage(event, context):
body_file = BytesIO(bytes(event["body"], "utf-8"))
form, files = parse_into_field_storage(
body_file,
event['headers']['Content-Type'],
body_file.getbuffer().nbytes
)
fileitem = files['file'][0]
print(fileitem.filename)
# Test if the file was uploaded
if fileitem.filename:
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
else:
message = 'No file was uploaded'
return {
"statusCode": 200,
"body": message
}
when i print the file from python i get this
I used diff and the binaries are different. I am thinking that the image files get parse double or something like that
I am guessing here I am doing something wrong
body_file = BytesIO(bytes(event["body"], "utf-8"))
I have tried different forms like
fp = io.BytesIO(event['body'].encode('utf-8'))
but it is basically the same.

file upload from Flask template to external APIs

I have divided my flask app with two-part API (Flask API) and web app (Flask template).
From the web app, I am trying to upload a file but on the API side, I am not able to send.
File upload is working from APIs side, I have tested from the postman.
Template (UI with port: 3010) and API (port: 3009)
Below is running on API side with port 3009
#app.route('/sources', methods=['POST', 'GET'])
def upload_file():
if request.method == 'POST':
try:
print(request.form.get('file')) # Not able to print file here
print(request.form.get('Language1')) # I am able to print it
if 'file' not in request.files:
resp = jsonify({'message' : 'No file part in the request'})
resp.status_code = 400
return resp
file = request.files['file']
if file.filename == '':
resp = jsonify({'message' : 'No file selected for uploading'})
resp.status_code = 400
return resp
if file and allowed_file(file.filename,'sources'):
sourceFileName = secure_filename(file.filename)
Lang1 = request.form.get('Language1')
Lang2 = request.form.get('Language2')
except Exception as e:
print(e)
resp = jsonify({'message' : 'Server Error'})
resp.status_code = 500
return resp
Below is running on UI side with port 3010
#app.route('/sources', methods=['POST'])
def upload_sources():
if request.method == "POST":
Language1 = request.form["Language1"]
Language2 = request.form["Language2"]
file = request.files["file"]
# File object is printing here like: [<FileStorage: 'source_text.docx' ('application/vnd.openxmlformats-officedocument.wordprocessingml.document')>]
print(file)
params = {
"Language1":Language1,
"Language2":Language2,
"file":file
}
headers = {'content-type': 'application/json'}
req = requests.post('http://localhost:3009/sources', headers=headers, data=params)
r = req.json()
print(r['message']) # I am getting response message : ['No file part in the request']
return redirect(url_for('fetch_sources'))
Below is working fine, just fetching uploaded file
#app.route('/sources', methods=['GET'])
def fetch_sources():
sources = requests.get('http://localhost:3009/sources')
source_data = sources.json()
if source_data:
return render_template('sources.html', sources=source_data['sources'])
I was sending a file object and the way which I was following that was incorrect...
I can not send file directly to API from webapp.
Here I have changed my code and it is working fine.
if request.method == 'POST':
file = request.files["file"]
sourceFileName = secure_filename(file.filename)
cwd = os.getcwd()+'/'
if 'temp' not in os.listdir(cwd):
os.mkdir(cwd + 'temp')
file.save(os.path.join(cwd + 'temp', sourceFileName))
with open(cwd + 'temp/'+ sourceFileName, 'rb') as f:
data_file = ImmutableMultiDict([("file", f)])
resp = requests.post(api_base_url + "/sources",
files=data_file)

Sending directory to client from server flask

I am trying to return a directory of images from the server to the client. I'm having a hard time understanding how to format my response so that the client is able to distinguish between the files.
What is the best practice way to accomplish what I am doing? my photos are kept in a tmp folder within the application. Here is my utils.py:
def get_multipart_fields():
final = {}
for file in os.listdir(os.path.dirname(os.path.realpath(__file__)) + '/tmp'):
try:
with open(os.path.dirname(os.path.abspath(__file__)) + '/tmp/' + os.path.join(file), "rb") as image_file:
encoded_string = base64.b64encode(image_file.read())
final[os.path.join(file)] = { 'filename': encoded_string }
except Exception as e:
print e
return final.to_string()
and my views.py:
#app.route('/download-files', methods=['GET'])
def gallery():
client = get_client()
resource = get_resource()
download_dir(client, resource, 'test-bucket')
file_names = get_multipart_fields()
m = MultipartEncoder(
fields=file_names
)
return Response(json.dumps(m), mimetype=m.content_type)
Where am I going wrong with this logic ? Any help would be greatly appreciated.

Generate PDF from html template and send via Email in Django

I'm trying to generate a pdf file from an HTML template using Weasyprint python package and I need to send it via email using.
Here's what i have tried:
def send_pdf(request):
minutes = int(request.user.tagging.count()) * 5
testhours = minutes / 60
hours = str(round(testhours, 3))
user_info = {
"name": str(request.user.first_name + ' ' + request.user.last_name),
"hours": str(hours),
"taggedArticles": str(request.user.tagging.count())
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name'] + '.pdf')
pdf = weasyprint.HTML(string=html).write_pdf(response, )
from_email = 'our_business_email_address'
to_emails = ['Reciever1', 'Reciever2']
subject = "Certificate from INC."
message = 'Enjoy your certificate.'
email = EmailMessage(subject, message, from_email, to_emails)
email.attach("certificate.pdf", pdf, "application/pdf")
email.send()
return HttpResponse(response, content_type='application/pdf')
But it returns an error as TypeError: expected bytes-like object, not HttpResponse
How can I generate and send a pdf file to an email from HTML template?
Update: With this updated code now it's generating pdf and sending an email but when I open attached pdf file from recieved email it says unsupported file formate data.
Here's the updated Code:
def send_pdf(request):
minutes = int(request.user.tagging.count()) * 5
testhours = minutes / 60
hours = str(round(testhours, 3))
user_info = {
"name": str(request.user.first_name + ' ' + request.user.last_name),
"hours": str(hours),
"taggedArticles": str(request.user.tagging.count())
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html).write_pdf()
from_email = 'arycloud7#icloud.com'
to_emails = ['abdul12391#gmail.com', 'arycloud7#gmail.com']
subject = "Certificate from Nami Montana"
message = 'Enjoy your certificate.'
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
# email.attach("certificate.pdf", pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'ISO-8859-1'
email.send()
return HttpResponse(pdf, content_type='application/pdf')
Help me, please!
Thanks in advance!
Here's the complete working version of above code:
user_infor = ast.literal_eval(ipn_obj.custom)
if int(user_infor['taggedArticles']) > 11:
# generate and send an email with pdf certificate file to the user's email
user_info = {
"name": user_infor['name'],
"hours": user_infor['hours'],
"taggedArticles": user_infor['taggedArticles'],
"email": user_infor['email'],
}
html = render_to_string('users/certificate_template.html',
{'user': user_info})
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename=certificate_{}'.format(user_info['name']) + '.pdf'
pdf = weasyprint.HTML(string=html, base_url='http://8d8093d5.ngrok.io/users/process/').write_pdf(
stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
to_emails = [str(user_infor['email'])]
subject = "Certificate from Nami Montana"
email = EmailMessage(subject, body=pdf, from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach("certificate_{}".format(user_infor['name']) + '.pdf', pdf, "application/pdf")
email.content_subtype = "pdf" # Main content is now text/html
email.encoding = 'us-ascii'
email.send()
As you can see from Weasysprint document, calling method write_pdf() will render the document in a single File.
http://weasyprint.readthedocs.io/en/stable/tutorial.html
Once you have a HTML object, call its write_pdf() or write_png()
method to get the rendered document in a single PDF or PNG file.
Also, they mention that
Without arguments, these methods return a byte string in memory.
So, you can get its PDF byte string and use it for attachment or pass the filename to write the PDF to.
There is a point that you can also send a writable file-like object to write_pdf().
If you pass a file name or a writable file-like object, they will
write there directly instead.
You can generate and attach the PDF file like this:
pdf = weasyprint.HTML(string=html).write_pdf()
...
email.attach("certificate.pdf", pdf, "application/pdf")
You can also send 200 Response if it was successful or 500 if it failed.
NOTE About SMTP Server
Normally you need an SMTP mail server for relaying your message to your destination.
As you can read from Django document send_mail need some configuration:
Mail is sent using the SMTP host and port specified in the EMAIL_HOST and EMAIL_PORT settings. The EMAIL_HOST_USER and EMAIL_HOST_PASSWORD settings, if set, are used to authenticate to the SMTP server, and the EMAIL_USE_TLS and EMAIL_USE_SSL settings control whether a secure connection is used.
Then you can use send_mail() with following parameters for relaying your message to the local SMTP server.
send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)
Attention: Don't miss authentication parameters.
This code works for me
template = get_template('admin/invoice.html')
context = {
"billno": bill_num,
"billdate": bill_date,
"patientname": patient_name,
"totalbill": total_bill,
"billprocedure": invoice_cal,
}
html = template.render(context)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)#, link_callback=fetch_resources)
pdf = result.getvalue()
filename = 'Invoice.pdf'
to_emails = ['receiver#gmail.com']
subject = "From CliMan"
email = EmailMessage(subject, "helloji", from_email=settings.EMAIL_HOST_USER, to=to_emails)
email.attach(filename, pdf, "application/pdf")
email.send(fail_silently=False)
Building on #Rishabh gupta answer:
import io
from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives
from weasyprint import HTML
context = { "name": 'Hello', }
html_string = render_to_string('myapp/report.html', context)
html = HTML(string=html_string)
buffer = io.BytesIO()
html.write_pdf(target=buffer)
pdf = buffer.getvalue()
email_message = EmailMultiAlternatives(
to=("youremailadress#gmail.com",),
subject="subject test print",
body="heres is the body",
)
filename = 'test.pdf'
mimetype_pdf = 'application/pdf'
email_message.attach(filename, pdf, mimetype_pdf)
email_message.send(fail_silently=False) # TODO zzz mabye change this to True

unable to detect request content_type

On a django server, I process uploaded zip files sent from a python script. But I am getting "" (a blank string) for file.content_type. What am I doing wrong?
#csrf_exempt
def Import( request ):
if request.method != 'POST':
return HttpResponseNotAllowed('Only POST here')
if not request.FILES or not request.FILES.get( u'file' ):
return HttpResponse('Must upload a file')
file = request.FILES[u'file']
if file.content_type == 'application/zip':
unzipped_dir = unzip_file( file )
uid = create_project( unzipped_dir )
shutil.rmtree( unzipped_dir )
py_ob = { }
py_ob['success'] = uid is not None
if uid is not None:
py_ob['id'] = uid
json_ob = simplejson.dumps(py_ob)
return HttpResponse( json_ob, mimetype="application/json" )
else:
return HttpResponseNotAllowed( 'Only POST zip files here' )
This is the script which sends the zip file up:
import sys
import os
import requests
if len (sys.argv) < 5:
print "pass in url, username, password, file"
else:
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
phile = sys.argv[4]
if os.path.exists(phile):
files = {'file': open( phile, 'rb' )}
r = requests.post( url, files=files, auth=( username, password ) )
if r.status_code == 200:
json_response = r.json()
if json_response['success']:
print "id: " + str( json_response['id'] )
else:
print "failure in processing bundle"
else:
print "server problem: " + str(r.status_code)
print r.text
else:
print "cannot find file to upload"
The Content-Type header is completely arbitrary (and optional) and not a good way to detect whether or not you're dealing with a valid ZIP file. Have you made sure your browser is supplying it?
Django's documentation tells us the same:
UploadedFile.content_type
The content-type header uploaded with the file (e.g. text/plain or application/pdf). Like any data supplied by the user, you shouldn’t
trust that the uploaded file is actually this type. You’ll still need
to validate that the file contains the content that the content-type
header claims – “trust but verify.”
You should be using zipfile.is_zipfile instead.

Categories