Javascript 上传';帆布';将图像数据传输到服务器

Javascript 上传';帆布';将图像数据传输到服务器,javascript,html,canvas,Javascript,Html,Canvas,我需要动态地将画布图像数据上传到服务器(数据库),也就是说,我需要创建一个表单和一个input=文件,并在没有任何用户交互的情况下发布图像数据。您可以以data:url的形式获取图像数据,但目前为止,这只适用于Firefox和Opera 您不需要文件输入,只需使用ctx.getImageData()获取数据并使用Ajax将其发布到服务器即可 看 但是你将无法在IE中获取图像数据,即使使用ExCanvas,这就是我使其工作的方式 我的服务器在谷歌应用程序引擎中。我使用jQuery.post将can

我需要动态地将画布图像数据上传到服务器(数据库),也就是说,我需要创建一个表单和一个input=文件,并在没有任何用户交互的情况下发布图像数据。

您可以以data:url的形式获取图像数据,但目前为止,这只适用于Firefox和Opera


您不需要文件输入,只需使用
ctx.getImageData()
获取数据并使用Ajax将其发布到服务器即可


但是你将无法在IE中获取图像数据,即使使用ExCanvas,这就是我使其工作的方式

我的服务器在谷歌应用程序引擎中。我使用jQuery.post将canvas.toDataURL()的输出作为post请求的一部分发送。数据URL是base64编码的图像数据。所以在服务器上,我解码它并将其转换为图像

import re 
import base64
class TnUploadHandler(webapp.RequestHandler):
    dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$')
    def post(self):
        uid = self.request.get('uid')
        img = self.request.get('img')

        imgb64 = self.dataUrlPattern.match(img).group(2)
        if imgb64 is not None and len(imgb64) > 0:
            thumbnail = Thumbnail(
                    uid = uid, img = db.Blob(base64.b64decode(imgb64)))
            thumbnail.put()
我从客户端发送如下数据:

$.post('/upload',
        {
            uid : uid,
            img : canvas.toDataURL('image/jpeg')
        },
        function(data) {});

这可能不是最好的方法,但它很有效。

这里是我去年写的一个在线签名应用程序的演示。这样做的优点是只将矢量数据发布到服务器。对于所有的路径信息,您还可以应用平滑算法或根据需要在持久化之前对其进行缩放

<canvas id="signature" width="300" height="100"></canvas>
<form method="post" id="signature_form" action="signing.aspx">
<input type="hidden" name="paths" id="paths"/>
    <p><label>Cover #</label> <input type="text" id="covernumber" name="covernumber"/>
    <input type="submit" id="save" value="Save"/>
</form>

封面#
我将路径数据存储到一个隐藏字段中,并将其发布到服务器

核心逻辑如下:

mouseDown: function(event) {
    var point = this.getRelativePoint(event);
    this.paths.push( [ point ] ); 
    this.ctx.fillRect(point.x,point.y,1,1);
    this.penDown = true;
    this.updateField();
},
mouseUp: function(event) {
    this.penDown = false;
    this.ctx.closePath();
    if ( Prototype.Browser.IE && event.srcElement.tagName != "INPUT" ) {
        var ver = getInternetExplorerVersion();
        if ( ver >= 8 && ver < 9 && document.selection ) {
            document.selection.empty();
        }
    }
},
mouseMove: function(event) {
    if ( this.penDown ) {
        var lastPath = this.paths[ this.paths.length - 1 ];
        var lastPoint = lastPath[ lastPath.length - 1 ];
        var point = this.getRelativePoint(event);
        lastPath.push( point );
        this.ctx.strokeStyle = "#000000";
        this.ctx.beginPath();
        this.ctx.moveTo(lastPoint.x,lastPoint.y);
        this.ctx.lineTo(point.x, point.y);
        this.ctx.stroke();
        this.ctx.closePath();
        this.updateField();
    }
},
updateField: function() {
    if ( this.field ) {
        this.field.value = this.paths.toJSON();
    }
}
mouseDown:函数(事件){
var point=this.getRelativePoint(事件);
this.path.push([point]);
这个.ctx.fillRect(点x,点y,1,1);
this.penDown=true;
this.updateField();
},
mouseUp:函数(事件){
this.penDown=false;
this.ctx.closePath();
if(Prototype.Browser.IE&&event.srcielement.tagName!=“输入”){
var ver=getInternetExplorerVersion();
如果(版本>=8&&ver<9&&document.selection){
document.selection.empty();
}
}
},
mouseMove:函数(事件){
如果(本·彭敦){
var lastPath=this.paths[this.paths.length-1];
var lastPoint=lastPath[lastPath.length-1];
var point=this.getRelativePoint(事件);
推送(点);
this.ctx.strokeStyle=“#000000”;
this.ctx.beginPath();
this.ctx.moveTo(lastPoint.x,lastPoint.y);
这个.ctx.lineTo(点x,点y);
这个.ctx.stroke();
this.ctx.closePath();
this.updateField();
}
},
updateField:function(){
如果(此字段){
this.field.value=this.path.toJSON();
}
}
下面是我的相关服务器端.Net代码(C#)

if(请求(“路径”)){
var objBitmap:Bitmap=新位图(300100);
var objGraphics:Graphics=Graphics.FromImage(objBitmap);
清晰(彩色,透明);
objGraphics.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
变量路径:数组=eval(请求(“路径”)| |[];
var p:int;
var q:int;
var路径:数组;
对于(p=0;p对于(q=1;q我就是这样解决的。使用JavaScript将图像发布为base64数组,然后使用PHP将其解码并保存为图像

客户端(JavaScript):

服务器端(PHP):


…还有safari(以及所有其他基于webkit的浏览器),有人让它真正起作用了吗?我从getImageData()中得到了返回的数据可以发布到服务器,但我不知道如何发布。我尝试在jQuery.ajax和jQuery.post中使用不同的选项,但我不知道如何在ajax请求中指定图像数据。我的服务器无法解释我发送的数据。我也找不到任何代码示例。您有任何指针吗?(我通过使用Curl和客户端执行相同的请求来确保服务器正常工作。)谢谢。可以在IE上使用fxCanvas(而不是ExCanvas)。您需要使用函数toDataURL(“image/png”,函数(fxUrl){…})。此答案中引用的资源已不存在。链接404s,这就是为什么指导原则规定您应该在答案中包含代码,而不仅仅是链接。getImageData返回原始像素数据,未压缩,不确定这是否是正确答案。如果img参数太大,将被删除,您是否遇到过此问题?@ernest我已搜索post restric您提到的选项(我知道get请求限制),我没有发现W3school说“POST请求对数据长度没有限制”限制在于服务器的配置。请参阅quota limitions@ccsakuweb关于post长度限制,几年前我编写了一个画布签名例程。通过将每一行存储到一个数组中,我可以将数据点发布到服务器,并在发布数据时重新创建服务器端。我将看看是否可以挖掘用于签名的代码当我开始工作时,发送原始图像数据的带宽效率不是很高,不是吗?最好将其转换为dataUrl并发送。
if ( Request("paths") ) {
    var objBitmap : Bitmap = new Bitmap(300, 100);
    var objGraphics : Graphics = Graphics.FromImage(objBitmap);
    objGraphics.Clear(Color.Transparent);
    objGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

    var paths:Array = eval(Request("paths")) || [];
    var p : int;
    var q : int;
    var path : Array;

    for ( p = 0; p< paths.length; p++ ) {
        var path = paths[p];
        if ( path.length == 1 ) {
            objGraphics.DrawRectangle(new Pen(Color.Black), path[0].x, path[0].y, 1, 1);
        } else {
          for ( q = 1; q<path.length; q++ ) {
              var prev = path[q-1];
              var curr = path[q];
              objGraphics.DrawLine(new Pen(Color.Black), parseInt(prev.x),parseInt(prev.y),parseInt(curr.x),parseInt(curr.y));
          }
        }
    }
    objBitmap.Save("C:\\temp\\" + Request("covernumber") + ".png", ImageFormat.Png);
    objBitmap.Dispose();
    objGraphics.Dispose();
}
$.post('/ajax/uploadthumbnail',
    {
        id : id,
        img : canvas.toDataURL("image/png")
    }, function(data) {
        console.log(data);
    });
$img = $_POST['img'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $_SERVER['DOCUMENT_ROOT'] . '/images/some_name.png';
file_put_contents($file, $data);