简体   繁体   中英

Image from canvas is not saved correctly

Good day to all users!
I have a problem that my screenshots rendered on canvas are not saved correctly.
Displaying screenshot on canvas using js

function retrieveImageFromClipboardAsBlob(pasteEvent, callback){
    if(pasteEvent.clipboardData == false){
        if(typeof(callback) == "function"){
            callback(undefined);
        }
    };
    var items = pasteEvent.clipboardData.items;
    if(items == undefined){
        if(typeof(callback) == "function"){
            callback(undefined);
        }
    };
    for (var i = 0; i < items.length; i++) {
        if (items[i].type.indexOf("image") == -1) continue;
        var blob = items[i].getAsFile();

        if(typeof(callback) == "function"){
            callback(blob);
        }
    }
}

window.addEventListener("paste", function(e){
    retrieveImageFromClipboardAsBlob(e, function(imageBlob){
        if(imageBlob){
            var canvas = document.getElementById("mycanvas");
            var ctx = canvas.getContext('2d');
            var img = new Image();
            img.onload = function(){
                canvas.width = this.width;
                canvas.height = this.height;
                ctx.drawImage(img, 0, 0);
            };
            var URLObj = window.URL || window.webkitURL;
            img.src = URLObj.createObjectURL(imageBlob);
        }
    });

    var cnv = document.getElementById("mycanvas");
    var sendCanvas = function (cnv) {
        var imgs = cnv.toDataURL('image/png').replace('data:image/png;base64,','');
        var sender = new XMLHttpRequest();
        sender.open('POST', '/temp.php', true);
        sender.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        sender.onreadystatechange = function () {
            if (sender.readyState == 4) {}
        };
        sender.send('imgs='+imgs);
    };
    sendCanvas(cnv);
}, false);

First, the screenshot is drawn on canvas and then sent to the php handler.
My html form has:

<canvas id="mycanvas">
<?php
    $imgs = str_replace(' ', '+', $_POST['imgs']);
    $imgs = base64_decode($imgs);
    $shootname = "screenshot".rand().".png";
    $screendir = "/mnt/ElmaFiles/".$shootname;
    file_put_contents($screendir, $imgs);
    $screennames .= $shootname.",";
?>
<p><input type="submit" name="submit1" class="btn success"></p>
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"</script>
<script src="/script11.js"></script>

In my understanding, files should be saved to the specified folder when I press ctrl + v. But it doesn't really work like that.
For example, I transfer 3 screenshots, but 5 screenshots are saved in my folder:

显示屏幕截图的目录列表

Please help me understand where is my mistake?
Thank you very much in advance!
I forgot to add: when 5 screenshots were saved, only the third and fourth could be opened from them, and the rest wrote an error like "incorrect format"

I did a little rewrite of the above which I hope will help solve some of the issues you were having.

The PHP that saves the image to disk should be explicitly targeted so that trying to call $_POST['imgs'] for a regular GET request will not cause issue. For sending the binary data to the server rather than XMLHttpRequest instead use fetch ~ a considerably more powerful api.

<?php

    error_reporting( E_ALL );
    ini_set( 'display_errors', 1 );
    
    if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['imgs'] ) ){
        ob_clean();
        
        $decoded=base64_decode( $_POST['imgs'] );
        
        #edit directory to suit. This is a sub-folder to where the script is currently running.
        $dir=sprintf('%s/images/tmp',__DIR__);
        
        
        
        $filename=sprintf('screenshot%s.png', rand() );
        $targetfile=sprintf('%s%s%s', realpath($dir), DIRECTORY_SEPARATOR, $filename );
        file_put_contents( $targetfile, $decoded );
        
        exit( $filename );
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title></title>
        <script>
            document.addEventListener('DOMContentLoaded',()=>{
            
                function getBlob(evt,callback){
                    if( evt.clipboardData == false || evt.clipboardData.items=='undefined' ){
                        return false;
                    };
                    let items = evt.clipboardData.items;
                    for( let i=0; i < items.length; i++){
                        let item=items[i];
                        if( ~item.type.indexOf('image') )callback( item.getAsFile() );
                    }
                }

                window.addEventListener('paste', function(e){
                    let canvas = document.querySelector('canvas');
                    let ctxt = canvas.getContext('2d');
                    
                    const callback=function( blob ){
                        if( blob ){
                            let img = new Image();
                                img.onload = function(){
                                    canvas.width=this.width;
                                    canvas.height=this.height;
                                    ctxt.drawImage( img, 0, 0 );
                                };
                                img.src = URL.createObjectURL(blob);
                            return true;
                        }
                        return false;
                    };
                    
                    getBlob( e, callback );
                    
                    let fd=new FormData();
                        fd.append('imgs', canvas.toDataURL('image/png').replace('data:image/png;base64,',''));
                        
                    fetch( location.href,{ method:'post', body:fd })
                        .then( r=>r.text() )
                        .then( text=>{
                            console.info('Screenshot %s saved',text )
                        })
                });
            });
        </script>
    </head>
    <body>
        <canvas></canvas>
    </body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM