Sending a plotly graph over flask - html

Right now I have a code that uses plotly to create a figure
def show_city_frequency(number_of_city = 10):
plot_1 = go.Histogram(
x=dataset[dataset.city.isin(city_count[:number_of_city].index.values)]['city'],
showlegend=False)
## Creating the grid for all the above plots
fig = tls.make_subplots(rows=1, cols=1)
fig.append_trace(plot_1,1,1)
fig['layout'].update(showlegend=True, title="Frequency of cities in the dataset ")
return plot(fig)
I want to incorporate this into a flask function and send it to an html template as a bytes io object using send_file. I was able to do this for a matplotlib just using:
img = io.BytesIO()
plt.plot(x,y, label='Fees Paid')
plt.savefig(img, format='png')
img.seek(0)
return send_file(img, mimetype='image/png')
I've read that I can do basically the same thing except using:
img = plotly.io.to_image(fig, format='png')
img.seek(0)
return send_file(img, mimetype='image/png')
but I can't seem to find where to download plotly.io. I've read that plotly offline doesn't work for Ubuntu so I am wondering if that is what my issue is as well. I am also open to new suggestions of how to send this image dynamically to my html code.

Related

PIL: Load image on <img> tag in Flask

I am getting an image file "plot.png" from s3 bucket using the following code
def read_froms3img(image_name):
ep_url=URL
access_id=ID_KEY
access_key=SECRET_KEY
s3_resource = boto3.resource(service_name = "s3",endpoint_url=ep_url, aws_access_key_id=access_id, aws_secret_access_key=access_key)
s3_client = boto3.client(service_name = "s3",endpoint_url=ep_url, aws_access_key_id=access_id , aws_secret_access_key=access_key)
bucket = s3_bucket
bucket = s3_resource.Bucket(bucket)
image = bucket.Object('Images/plot.png')
img_data = image.get().get('Body').read()
return Image.open(io.BytesIO(img_data))
I am calling the above function as below and pass the "contents" to the render_template('data.html)
contents = read_froms3img("plot.png")
return render_template('data.html', form_data = form_data, html_code = html, filename = contents)
And if i do contents.show(), it loads the image in my local.
data.html:
<img src="{{filename}}" height="50%" width="65%">
But the image is not loading in the frontend, if i do inspect element, i can see the below code in the tag
<img src="<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=640x480 at 0x257583E0DF0>" height="50%" width="65%">
How to display the image in the tag in the html page.
Please help.
Thanks,
Updated Answer
I think you want to allow the web-browser to view an image stored in an S3 bucket. So, make your HTML point to a Flask view like this:
<img src="/S3image/REFERENCE">
where REFERENCE is something that uniquely identifies an image on your S3. Then in your Flask app:
from flask import Response
#app.route('/S3image/<ref>')
def serveS3(ref):
...
... all your code except your 'return' statement
...
return Response(img_data, mimetype='image/png')
Original Answer
You can't return a Python PIL Image object to a web-browser... they don't understand Python. You need to return a PNG image, and you have one already in your variable img_data, so just return that with the appropriate MIME type.
It will look something like:
from flask import Response
....
....
return Response(img_data, mimetype='image/png')

Firebase Cloud Functions-ImageMagick CLI PDF to images

I am trying to work with Firebase Cloud Functions, and ImageMagick, similar to how the thumbnail demo is done. By re-purposing the demo script, I want to execute a CLI command for ImageMagick to split PDF pages to images.
convert -density 150 presentation.pdf -quality 90 output-%3d.jpg
The snippet
exports.splitPdfPages = functions.storage.object().onFinalize(async (object) => {
const fileBucket = object.bucket; // The Storage bucket that contains the file.
const filePath = object.name; // File path in the bucket.
const contentType = object.contentType; // File content type.
const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.
// Download file from bucket.
const bucket = admin.storage().bucket(fileBucket);
const tempFilePath = path.join(os.tmpdir(), fileName);
const tempSplitImagesPath = tempFilePath.replace(".png", "_%3d.png");
await bucket.file(filePath).download({destination: tempFilePath});
console.log('PDF downloaded locally to', tempFilePath);
// Generate split page images using ImageMagick.
await spawn('convert', ['-density', '150', tempFilePath, '-quality', '90', tempSplitImagesPath]);
console.log('pages split images created at', tempFilePath);
...
// Uploading the split images.
...
// Once the thumbnail has been uploaded delete the local file to free up disk space.
return fs.unlinkSync(tempFilePath);
});
Unfortunately, I'm encountering errors in the Cloud Functions log indicating the statement error
ChildProcessError: convert -density 150 /tmp/7eCxdDKqCb0rlYVw3AYf__foobar.pdf -quality 100 /tmp/7eCxdDKqCb0rlYVw3AYf__foobar_%3d.png failed with code 1
I searched for resolution to the error, but it only indicates that whitespaces are the main reason for the issue (which based on my statement doesn't have any). Invoking generateThumbnail function works properly, so I'm presuming its based on my changes
Am I missing something to properly call the ImageMagick command for converting PDF pages to image?
Looking forwad to hearing from you.

How would you create a downloadable pdf in a client side app?

One of our requirements for an admin tool is to create a form that can be filled and translated to a downloadable pdf file. (A terms and condition with blank input fields to be exact).
I did some googling and tried creating a form in html and css and converted it into a canvas using the html2canvas package. Then I used the jspdf package to convert it into a pdf file. The problem is that I cannot get it to fit and resize accordingly to an a4 format with correct margins. I'm sure I can get to a somewhat working solution if I spend some time on it.
However, my real question is how would you guys solution this? Is there a 3rd party app/service that does this exact thing? Or would you do all this in the server side? Our current app is using angular 7 with firebase as our backend.
Cheers!
I was able to use the npm package pdfmake to create a dynamic pdf based on user information the user provided while interacting with my form. (I was using React) It opened the pdf in a new tab and the user is able to save the pdf. In another application (still React),
I used the same package to create a receipt so you can customize the size of the "page". We created the pdf and used the getBase64() method and sent the pdf as an email attachement.
My service function:
getEvidenceFile(id: number, getFileContent: boolean) {
return this.http.get(environment.baseUrl + ‘upload’ + ‘/’ + id , {responseType: ‘blob’ as ‘json’})
.map(res => res);
}
My component function called from the selected item of a FileDownload…
FileDownload(event: any) {
// const blob = await this.callService.getEvidenceFile(event.target.value, true);
// const url = window.URL.createObjectURL(blob);
this.callService.getEvidenceFile(event.target.value, true).subscribe(data => {
var binaryData = [];
binaryData.push(data);
var downloadLink = document.createElement(‘a’);
downloadLink.href = window.URL.createObjectURL(new Blob(binaryData));
document.body.appendChild(downloadLink);
downloadLink.click();
});
}

How do I parse a html page using nodejs to find a qr code?

I want to parse a web page, searching for QRcodes in the page. When I find them, I am going to read them using the QRcode npm module.
The hard part is, I don't know how to parse the html page in a way I can detect the only the image tags that contains a QRcode inside it.
I tried finding some kind of pattern in the images that contain a Qr code, but it usually starts with "?qr" but I think the ending is different everytimwe.
I'm using the module require-promise to get the raw html, and then I parse through it
const rp = require('request-promise');
const url = 'https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States';
rp(url)
.then(function(html){
//success!
console.log(html);
})
.catch(function(err){
//handle error
});
I want to be able to download the image of the QRcode.
You need to pass the html returned into something like https://www.npmjs.com/package/node-html-parser
const rp = require('request-promise');
const parser = require('node-html-parser');
const url = 'https://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States';
rp(url)
.then(function(html){
const data = parser.parse(html);
console.log(JSON.stringify(data));
})
.catch(function(err){
//handle error
});
Then you can access things off the data object to find the QR code

Python + Selenium + PhantomJS render to PDF - multiple files

I am trying to addapt the code found in
Python + Selenium + PhantomJS render to PDF
so I instead of saving one web page as a pdf file, I can iterate over a list of urls and save each one with a specific name (from another list).
count = 0
while count < length:
def execute(script, args):
driver.execute('executePhantomScript', {'script': script, 'args' : args })
driver = webdriver.PhantomJS('phantomjs')
# hack while the python interface lags
driver.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
driver.get(urls[count])
# set page format
# inside the execution script, webpage is "this"
pageFormat = '''this.paperSize = {format: "A4", orientation: "portrait" };'''
execute(pageFormat, [])
# render current page
render = '''this.render("test.pdf")'''
execute(render, [])
count+=1
I tested modifying
render = '''this.render("test.pdf")'''
to
render = '''this.render(names[count]+".pdf")'''
so as to include the each name in the list using count but have not been successful.
Also tried:
dest = file_user[count]+".pdf"
render = '''this.render(dest)'''
execute(render, [])
But did not work either.
I greatly appreciate a suggestion for the appropriate syntax.
It must be very simple but I am a noobie.
Use string formatting:
render = 'this.render("{file_name}.pdf")'.format(file_name=names[count])