Django: Take a screenshot with html2canvas and save the image on the server with Django-Rest-Framework API
Hey folks, Let’s say you have a section on your webpage which you want to capture as an image and save on the backend server for later use, there are some external libraries which do the job for you like Django ScreemShot, etc. But we can do it ourselves without using any Django libraries.
Today, let me show you how to capture and save the screenshot using Html2canvas and python with the Django rest framework.
Html2Canvas
Html2Canvas is a straightforward, easy, and ready to use JavaScript library, It is a great tool to convert a section on your webpage or the whole webpage into an image file. I will use a CDN version of it but you can also download it from here. Put the below script in the head section of your webpage and we are ready to use Html2Canvas:
<script type=”text/javascript” src=”https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
HTML
This is the full HTML page where we have a section <div id=”section_to_capture”> and we will be capturing a screenshot of this <div> and post it with Django-rest-framework API endpoint
<!DOCTYPE html><html>
<head>
<title>Html2canvas screenshot</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script type="text/javascript" src="/static/js/jSignature.min.js"></script>
<script type="text/javascript" src="/static/js/django_jsignature.js"></script> <div id="div_id_signature" class="form-group">
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
</head>
<body><div class="container">
<div class="row">
<div class="col-xs-12">
<h1 class="text-center">Html2canvas</h1>
<div id="section_to_capture"> <h3>Html2canvas screenshot</h3><p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p>
</div><button type="button" id="submit" class="btn btn-primary">Save Screenshot</button></div></div></div>
</body>
</html>
JavaScript
This is the magic javascript code here, which does the capturing job. here, we will use the html2canvas library method call html2canvas() which takes an element as an argument for which we need to capture a screenshot.
I have added a javascript function b64toBlob which converts a base64 object to a Blob object.
$(function() {
$("#submit").click(function() {
html2canvas($("#section_to_capture"), {
onrendered: function(canvas) {
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
image_data = canvas.toDataURL('image/png'); # use can use image/jpg to generate JPG format image
var block = image_data.split(";");
var contentType = block[0].split(":")[1]
var realData = block[1].split(",")[1];
var blob = b64toBlob(realData, contentType);
var formData = new FormData();
formData.append("screenshot", blob, 'screenshot.png');
$.ajax({
url: "/api/save_screenshot/",
type: "POST",
timeout: 0,
processData: false,
mimeType: "multipart/form-data",
contentType: false,
data: formData,
dataType:"json",
success: function (data) {
alert("Screenshot saved successfully!");
},
error: function (e) {
console.log(e);
}
}).done(function(o) {
});
}
});
});
});
urls.py
Now, let's register a URL api/save_screenshot/. This API endpoint is called by the above JavaScript code in the Ajax section.
from django.urls import path
from .views import *
urlpatterns = [
path('api/save_screenshot', SaveScreenshot.as_view(), name='save-screenshot')
models.py
I am creating a sample model with one filed screenshot, use the existing model, or create a model like below:
class Screenshot(models.Model):
screenshot = models.ImageField(upload_to='img/screenshots/', help_text='Html2canvas screenshot')
views.py
here, this is the rest_framework CreateAPIView, I am allowing the API endpoint to be accessible in public with setting permission_classes to allow any.
from rest_framework.generics import CreateAPIViewclass SaveScreenshot(CreateAPIView):
serializer_class = ScreenshotCreateSerializer
permission_classes = [AllowAny]
serializer.py
Now let’s add ScreenshotCreateSerializer to save the image in the model.
class ScreenshotCreateSerializer(ModelSerializer):
class Meta:
model = Screenshot
fields = [
'screenshot'
]
Final output
Here is the final output image which I got saved in the backend server: