djangolinuxselenium-chromedriverwebpage-screenshot

Django view to PNG


I'm writing django webapp, and part of it is to generate view and convert it to png image. (any ideas other then below are appreciated). I've looked at some tools to convert "html to png", but there is mainly problem with {%static files and templates. Another approach is to render page using django templates in browser, and take screenshot. It can be done using "chromedriver" + selenium. I was able to do it in my local ubuntu. But on production - all I've got is remote (ssh) access to some linux bash, where my application is hosted. I've created venv, pip-installed selenium and (chromedriver-py or chromedriver-binary). For the second one - it looks like it is closer to start working, but I've got error message: SessionNotCreatedException Message: session not created: probably user data directory is already in use, please specify a unique value for --user-data-dir argument, or don't use --user-data-dir

Stackoverflow says, that I should somehow put there a path to my chrome installation's user dir, but is there any chrome installation in that console bash of mine?

Any ideas how to move forward ? or any other ideas how to do it? My code:

import chromedriver_binary   


def render_to_png(request ):  
      
     
    chrome_options = webdriver.ChromeOptions() 
    chrome_options.add_argument("--headless")  # Run in headless mode (no GUI)
    driver = webdriver.Chrome( options=chrome_options) 
    driver.get("someurl.com") 
    driver.save_screenshot("x.png")
     
    driver.quit()
    return HttpResponse(status=200)

UPDATE: So tu summarize where I am so far:

  1. imgkit + wkhtmltoimage
  1. weasyprint
  1. I'm not continuing with selenium + chrome, as it is only console bash server...
  2. so the last hope in html2canvas... I'll leave comment as soon as have some results..

Solution

  • Well here is an elaborated answer which might help:

    For using html2canvas in django you can need cdn link: https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js

    Client Side Script

    <script>
        function captureAndUpload() {
            const element = document.getElementById('capture-area'); // replace with your html element id or = document.body for whole page
            
            html2canvas(element).then(canvas => {
                canvas.toBlob(blob => {
                    const formData = new FormData();
                    formData.append('image', blob, 'screenshot.png');
    
                    fetch('/upload-image/', { // replace with djgango url
                        method: 'POST',
                        body: formData,
                        headers: {
                            'X-CSRFToken': getCSRFToken() // include CSRF token if CSRF enabled
                        }
                    })
                    .then(response => response.json())
                    .then(data => {
                        console.log('Upload successful:', data);
                    })
                    .catch(error => {
                        console.error('Error uploading image:', error);
                    });
                }, 'image/png');
            });
        }
    
        // function to get CSRF token
        function getCSRFToken() {
            const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
            return csrfToken;
        }
    </script>
    

    The button

    <button onclick="captureAndUpload()">Capture and Upload</button>
    

    Django server side logic

    from django.http import JsonResponse
    from django.views.decorators.csrf import csrf_exempt
    from django.core.files.storage import default_storage
    
    @csrf_exempt  # Use this only if CSRF tokens are not included
    def upload_image(request):
        if request.method == 'POST' and 'image' in request.FILES:
            image = request.FILES['image']
            file_path = default_storage.save(f'uploads/{image.name}', image)
            return JsonResponse({'message': 'Image uploaded successfully', 'file_path': file_path})
        return JsonResponse({'error': 'Invalid request'}, status=400)
    

    Urls.py

    ...
    
    urlpatterns = [
        path('upload-image/', upload_image, name='upload-image'),
    ]
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    

    One more thing to add in settings.py

    MEDIA_URL = '/media/'
    MEDIA_ROOT = BASE_DIR / 'media'