How to upload an image with flask and store in couchdb? - couchdb

A previous question asks how to retrieve at attachment from couchdb and display it in a flask application.
This question asks how to perform the opposite, i.e. how can an image be uploaded using flask and saved as a couchdb attachment.

Take a look at the example from WTF:
from werkzeug.utils import secure_filename
from flask_wtf.file import FileField
class PhotoForm(FlaskForm):
photo = FileField('Your photo')
#app.route('/upload/', methods=('GET', 'POST'))
def upload():
form = PhotoForm()
if form.validate_on_submit():
filename = secure_filename(form.photo.data.filename)
form.photo.data.save('uploads/' + filename)
else:
filename = None
return render_template('upload.html', form=form, filename=filename)
Take a look at the FileField api docs. There you have a stream method giving you access to the uploaded data. Instead of using the save method as in the example you can access the bytes from the stream, base64 encode it and save as an attachment in couchdb, e.g. Using put_attachment. Alternatively, the FileStorage api docs suggest you can use read() to retrieve the data.

Related

AWS Object Lambda using PyPDF2 to send back encrypted PDF

My AWS OBJECT Lambda Function gets an unencrypted PDF via the Object Lambda inputS3Url. I want to use PyPDF2 to convert this to encrypted PDF, and send back via s3.write_get_object_response. How do I do this?
s3_url = object_get_context["inputS3Url"]
url=s3_url
response = requests.get(url)
my_raw_data = response.content
[SAVE ENCRYPTED my_raw_data TO VARIABLE so it can returned via S3.write_get_object_response - HOW?]
s3 = boto3.client('s3')
s3.write_get_object_response(
Body= [WHAT WOULD GO HERE?]
RequestRoute=request_route,
RequestToken=request_token)
The docs got you! Encrypting PDFs and Streaming Data is what you need (at least if I got you right; let me know if you want to achieve something else than getting a password-protected PDF on S3)
Not tested, but something like this
from PyPDF2 import PdfReader, PdfWriter
from io import BytesIO
reader = PdfReader(BytesIO(my_raw_data))
writer = PdfWriter()
# Add all pages to the writer
for page in reader.pages:
writer.add_page(page)
# Add a password to the new PDF
writer.encrypt("my-secret-password")
# Save the new PDF to a file
with BytesIO() as bytes_stream:
writer.write(bytes_stream)
bytes_stream.seek(0)
s3 = boto3.client('s3')
s3.write_get_object_response(
Body=bytes_stream,
RequestRoute=request_route,
RequestToken=request_token
)

Flask: delete file from server after send_file() is completed

I have a Flask backend which generates an image based on some user input, and sends this image to the client side using the send_file() function of Flask.
This is the Python server code:
#app.route('/image',methods=['POST'])
def generate_image():
cont = request.get_json()
t=cont['text']
print(cont['text'])
name = pic.create_image(t) //A different function which generates the image
time.sleep(0.5)
return send_file(f"{name}.png",as_attachment=True,mimetype="image/png")
I want to delete this image from the server after it has been sent to the client.
How do I achieve it?
Ok I solved it. I used the #app.after_request and used an if condition to check the endpoint,and then deleted the image
#app.after_request
def delete_image(response):
global image_name
if request.endpoint=="generate_image": //this is the endpoint at which the image gets generated
os.remove(image_name)
return response
Another way would be to include the decorator in the route. Thus, you do not need to check for the endpoint. Just import after_this_request from the flask lib.
from flask import after_this_request
#app.route('/image',methods=['POST'])
def generate_image():
#after_this_request
def delete_image(response):
try:
os.remove(image_name)
except Exception as ex:
print(ex)
return response
cont = request.get_json()
t=cont['text']
print(cont['text'])
name = pic.create_image(t) //A different function which generates the image
time.sleep(0.5)
return send_file(f"{name}.png",as_attachment=True,mimetype="image/png")
You could have another function delete_image() and call it at the bottom of the generate_image() function

Reading blob from database without saving to disk in Python

I am trying to read a set of records from db which has a blob field. I am able to read it but not without saving it to disk first.
cursor.execute("select image ,id,
department from dept_master")
depdata = cursor.fetchall()
for row in depdata:
file_like = io.BytesIO(row[0])
file = PIL.Image.open(file_like)
target = os.path.join("/path-to-save/", 'folder-save')
destination = "/".join([target, file.filename])
file.save(destination)
How can I read it and display it without first saving to disk ?
I am planning to use render_template to display the data
To serve the images from a blob field, you need to create a separate route which serves the actual image data specifically, then in a template include links which load the files from this route.
There's no need to use PIL here, as the blob field gives you bytes data. You run that through BytesIO to get a _io.BytesIO object, which can be passed straight to Flask's send_file function.
from io import BytesIO
from flask import send_file
#app.route('/image/<int:ident>')
def image_route(ident):
# This can only serve one image at a time, so match by id
cursor.execute("select image from dept_master WHERE id = ?", (ident,)
result = cursor.fetchone()
image_bytes = result[0]
bytes_io = BytesIO(image_bytes)
return send_file(bytes_io, mimetype='image/jpeg')
At this stage you should be able to hit /image/1 and see the image in your browser for the row with id 1.
Then, somewhere in a template, just include the link for this with:
<img src='{{ url_for("image_route", ident=image_ident) }}' />
This assumes that image_ident is available in the template. You might need to replace this variable name with something which exsists (could be a variable within a for loop which denotes the image id to pull).
Let me know if this needs further explaining.

How to create URL query string in flask

I am using flask and python3 to upload a video on server. The result is saved in format(filename)+result.jpg , where filename is the videoname
This image result was visible on browser with url /video_feed before appending result.jpg with string
How can I now access the url to see result.jpg
#app.route('/video_feed_now')
def video_feed_now():
#return send_file('result.jpg', mimetype='image/gif')
return send_file(format(filename)+'result.jpg', frame)
The variable $frame is undefined.
In your case, I suggest to use send_from_directory.
Here is usage sample.
#app.route('/uploads/<path:filename>')
def download_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename, as_attachment=False)
Besides, you can refer this In Flask, how can I generate a dynamic URL upon button click?
filename = secure_filename(file.filename)
cv2.imwrite(format(filename)+'result.jpg', frame)
#app.route('/video_feed_now/<filename>')
def video_feed_now(filename):
return send_file(format(filename), mimetype='image/gif')

Tweepy Search API Writing to File Error

Noob python user:
I've created file that extracts 10 tweets based on the api.search (not streaming api). I get a screen results, but cannot figure how to parse the output to save to csv. My error is TypeError: expected a character buffer object.
I have tried using .join(str(x) and get other errors.
My code is
import tweepy
import time
from tweepy import OAuthHandler
from tweepy import Cursor
#Consumer keys and access tokens, used for Twitter OAuth
consumer_key = ''
consumer_secret = ''
atoken = ''
asecret = ''
# The OAuth process that uses keys and tokens
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(atoken, asecret)
# Creates instance to execute requests to Twitter API
api = tweepy.API(auth)
MarSec = tweepy.Cursor(api.search, q='maritime security').items(10)
for tweet in MarSec:
print " "
print tweet.created_at, tweet.text, tweet.lang
saveFile = open('MarSec.csv', 'a')
saveFile.write(tweet)
saveFile.write('\n')
saveFile.close()
Any help would be appreciated. I've gotten my Streaming API to work, but am having difficulty with this one.
Thanks.
tweet is not a string or a character buffer. It's an object. Replace your line with saveFile.write(tweet.text) and you'll be good to go.
saveFile = open('MarSec.csv', 'a')
for tweet in MarSec:
print " "
print tweet.created_at, tweet.text, tweet.lang
saveFile.write("%s %s %s\n"%(tweet.created_at, tweet.lang, tweet.text))
saveFile.close()
I just thought I'd put up another version for those who might want to save all
the attributes of a tweepy.models.Status object, if you're not yet sure which attributes of each tweet you want to save to file.
import json
search_results = []
for status in tweepy.Cursor(api.search, q=search_text).items(5000):
search_results.append(status._json)
with open('search_results.json', 'w') as f:
json.dump(search_results, f)
The first block will store the search results into a list of dictionaries, and the second block will output all the tweets into a json file.
Please beware, this might use up a lot of memory if the size of your search results is very big.
This is Twitter's classic error code when something is wrong while sending a wrong image.
Try to find images you are trying to upload and check the format of the images.
The only thing I did was erase the images that MY media player of Windows canĀ“t read and that's all! the script run perfectly.

Resources