使用 Ajax 上传 base64 图像

IT技术 javascript jquery ajax symfony base64
2021-02-01 15:30:01

我的客户让用户选择一张图片,裁剪并调整它的大小,然后显示它(在<img>DOM 元素中)。
如果图片没问题,用户可以将其上传到服务器以便保存。

由于 Ajax 请求,我想上传。

我在互联网上找到了大量示例来上传从客户端 PC 检索的原始图像例如:

$( '#my-form' )
  .submit( function( e ) {
    $.ajax( {
      url: 'http://host.com/action/',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );

如果我决定上传通过表单输入检索到的图片,这将正常工作。

就我而言,我想上传修改后的图片(保存在<img>元素中)而不是原始图片。
这张图片存储为base64图片(参考:我使用croppie.js库生成图片)。

我不知道如何用 Ajax 上传这张图片。

我试图将它作为常规参数上传,但在服务器端,img 是一个空字符串:

var url = 'http://host.com/action/';
var data = {};
data.img = $('img#generated-image').attr('src');

$.ajax({url: url, type: "POST", data: data})
  .done(function(e){
    // Do something
  });
// RESULTS in a empty data.img on the server side.

我的问题是服务器在检索“img”参数时有一个空字符串。我怀疑图像可能太大而无法传递到服务器或其他一些我不明白的问题......

所以我想知道使用 Ajax 请求而不使用表单将 base64 图像发送到服务器正确方法是什么

谢谢你的帮助。

编辑

似乎是 xmlHTTP POST 参数大小问题。我试图减少图像字符串表示的字符数,服务器现在可以检索它。

编辑2

php.ini 文件中 post_max_size 设置为 8M,而图片大小只有 24K。所以问题不存在。
我在 Symfony2 框架中使用 PHP。
也许是 Symfony2 的限制。

2个回答

我最终决定将 base64 图像转换为 Blob,以便它可以通过带有 formData 对象的 Ajax 请求发送,如下所示。它节省了上传带宽(base64 比其二进制等价物多占用 33% 的位)并且我找不到不传输 base64 参数的原因(肯定是由于某处的大小限制)。

base64ToBlob 函数基于此对另一个问题的回答

function base64ToBlob(base64, mime) 
{
    mime = mime || '';
    var sliceSize = 1024;
    var byteChars = window.atob(base64);
    var byteArrays = [];

    for (var offset = 0, len = byteChars.length; offset < len; offset += sliceSize) {
        var slice = byteChars.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);
    }

    return new Blob(byteArrays, {type: mime});
}

我的JS代码:

var url = "url/action";                
var image = $('#image-id').attr('src');
var base64ImageContent = image.replace(/^data:image\/(png|jpg);base64,/, "");
var blob = base64ToBlob(base64ImageContent, 'image/png');                
var formData = new FormData();
formData.append('picture', blob);

$.ajax({
    url: url, 
    type: "POST", 
    cache: false,
    contentType: false,
    processData: false,
    data: formData})
        .done(function(e){
            alert('done!');
        });

在 Symfony2 中,由于以下原因,我可以检索图像:

$picture = $request->files->get('picture');
是的,我看到了几个非常相似的 base64ToBlob 函数版本。还有一些其他功能几乎做同样的事情。很高兴找到根作者。:-) 谢谢你的帮助。
2021-03-19 15:30:01
@CotyEmbry 我认为 Jeremy 很生气,因为谁复制了他的代码将版权放在上面,而代码不是他写的,而不是他的代码的重用 :)
2021-03-20 15:30:01
有趣的是,您找到的代码似乎主要来自我在此处的回答,其中一些变量重命名并包装以用作 Node module。我喜欢他把自己的名字写在版权上,当按行数计算时,我的代码比他的多。也许我应该起诉他。;) 我将冒昧更改您帖子中的链接以指向我的答案。
2021-04-06 15:30:01
这个网站上发布的所有代码都不是像知识共享之类的吗?如果您对有人复制您的代码 id 感到不安,请假定永远不要公开发布。我的两分钱。
2021-04-06 15:30:01

Nitseg 的回答效果很好。另外,如果您必须在 ajax 调用中使用身份验证令牌,我想添加以下几行。同样,请先查看 Nitseg 的回答以了解更多详细信息。

var formData = new FormData();
var token = "<YOUR-TOKEN-HERE>";
formData.append("uploadfile", mediaBlob);        

jQuery.ajax({
    url: url,
    type: "POST",
    cache: false,
    contentType: false,
    processData: false,
    data: formData,
    beforeSend: function (xhr){ 
        xhr.setRequestHeader("Authorization", "Bearer " + token); 
    }
})
.done((e) => {
    // It is done.
})
.fail((e) => {
    // Report that there is a problem!
});