画布中的图像未正确保存
Posted
技术标签:
【中文标题】画布中的图像未正确保存【英文标题】:Image from canvas is not saved correctly 【发布时间】:2021-06-23 05:50:21 【问题描述】:祝所有用户美好的一天! 我的问题是我在画布上呈现的屏幕截图未正确保存。 使用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);
首先,屏幕截图在画布上绘制,然后发送到 php 处理程序。 我的 html 表单有:
<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>
在我的理解中,当我按下 ctrl + v 时,文件应该被保存到指定的文件夹中。但它并不是真的那样工作。 比如我传输了3张截图,但是我的文件夹里保存了5张截图:
请帮助我理解我的错误在哪里? 非常感谢您! 忘了补充:保存5张截图时,只能打开第三张和第四张,其余的都写了“格式不正确”之类的错误
【问题讨论】:
注意typeof(callback)
中不需要括号,可以改为typeof callback
。
@luekbaja 感谢您的建议,我最近开始学习网络语言。但这并没有解决我的问题:(
temp.php
是做什么的?那应该保存文件吗?您可以添加其中的内容吗?或者您是否满意它可以正常工作?
@ProfessorAbronsius 对不起。没注意到我错了。我的 html 表单是 temp.php
OK - 所以你将 AJAX 请求发送到同一页面?那是显示的那段代码 - 以$imgs = str_replace(' ', '+', $_POST['imgs']);
开头??
【参考方案1】:
我对上面的内容做了一点重写,希望能帮助解决你遇到的一些问题。
应该明确定位将图像保存到磁盘的 PHP,以便尝试为常规 GET 请求调用 $_POST['imgs']
不会导致问题。要将二进制数据发送到服务器而不是 XMLHttpRequest
,请改用 fetch
~ 一个相当强大的 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>
【讨论】:
谢谢!它真的很有帮助。但是,进入画布的第一个屏幕截图仍然是空的。其余的屏幕截图创建没有问题。 真的吗?似乎工作正常...啊~发现一个小错误。将str_replace(' ', '+', $_POST['imgs'] )
更改为简单的$_POST['imgs']
感谢您的帮助!但是这种方法仍然没有帮助我。第一个屏幕截图只是一个白色画布。 :(
在我删除了那部分(上面提到的)之后,它每次都能正常工作?!
如果我改变你上面描述的方法,那么第一个屏幕截图仍然只是一个白色的画布,其余的屏幕截图都是从原始截图中裁剪出来的。我决定不改变方法,而是试图弄清楚为什么第一个屏幕截图被加载为白色画布。以上是关于画布中的图像未正确保存的主要内容,如果未能解决你的问题,请参考以下文章
将图像加载到画布上并放大/缩小并移动它以适应并保存画布上的内容