You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fabric.js Canvas导出BMP转Base64后还原为二进制文件出现格式错误问题求助

Fabric.js Canvas导出BMP转Base64后还原为二进制文件出现格式错误问题求助

我现在遇到一个棘手的问题:尝试把Fabric.js Canvas通过toDataURL返回的Base64数据转换成BMP格式文件时,总是提示“文件格式不正确”。下面是我的操作流程和代码,麻烦各位帮忙看看哪里出问题了?

我的操作步骤

  • 从Fabric.js Canvas获取BMP格式的dataURL:
    dataURL = canvas.toDataURL({
      format: 'bmp',
      quality: 1.0
    });
    
  • 提取dataURL里的Base64部分:
    dataURLto64 = dataURL.substr(dataURL.lastIndexOf(',') + 1,
    dataURL.length -
    dataURL.lastIndexOf(',') - 1);
    
  • 客户端通过Ajax分块把Base64字符串传到服务器,每块大小90000字符,并且对每块做了两次encodeURI编码;服务器接收后把每块追加写入到TXT文件中。
  • 服务器端读取TXT文件的内容,验证Base64的长度是4的倍数(确实是,不需要补=),然后用Convert.FromBase64String转成字节数组,最后写入成BMP文件。

客户端分块传输代码(关键部分)

async function exportarCanvasF1(nombrearchivo, start_) {       
  let start = Number(start_);
  var chunkSize = 90000; 
  let start_limite = (start == 0 ? Number(start_) : Number(start_)) + chunkSize;      

  if (start_limite > dataURL.length) {
    start_limite = (start_limite - (start_limite -  dataURL.length - 1));
  }
  if (Number(start) + chunkSize > dataURL.length) {
    chunkSize = chunkSize - ((Number(start) + chunkSize) - dataURL.length) + 1;           
  }
          
  let dataURL_;
    
  if (Number(start) < dataURL.length) {           
    dataURL_ = dataURL.substr(start, chunkSize);
    dataURL_ = encodeURI(encodeURI(dataURL_));
               
    $.ajax({
      type: "POST",
      url: "Respuestaajax.aspx/Respuestaaj",
      contentType: "application/json; charset=utf-8",
      data: 
      '{"parametro":"funcion","valor":"TroceadoFileBase64","tabla":"' + dataURL_ + '","campo":"' + nombrearchivo + '","criterio":"' + start_limite + '","v1":""}',
      dataType: "json",
      success: function (devolucion) {
        if (devolucion.d) {
          var d = JSON.parse(devolucion.d);
          exportarCanvasF1(d[0][1], d[1][1]);
        }
      },
      error: function (req, status, error) {}
    });
  } else {
    // 最后一块传输,完成后调用服务器的收尾方法
    dataURL_ = dataURL.substr(start, chunkSize);
    console.log("Length chunk: " + dataURL_.length);
    dataURL_ = encodeURI(encodeURI(dataURL_));
          
    $.ajax({
      type: "POST",
      url: "Respuestaajax.aspx/Respuestaaj",
      contentType: "application/json; charset=utf-8",
      data: '{"parametro":"funcion","valor":"TroceadoFileBase64","tabla":"' + dataURL_ + '","campo":"' + nombrearchivo + '","criterio":"' + start_limite + '","v1":""}',
      dataType: "json",
      success: function (devolucion) {
        if (devolucion.d) {
          var d = JSON.parse(devolucion.d);
          $.ajax({
            type: "POST",
            url: "Respuestaajax.aspx/Respuestaaj",
            contentType: "application/json; charset=utf-8",
            data: '{"parametro":"funcion","valor":"TroceadoFileBase64_fin","tabla":"' + nombrearchivo + '","campo":"","criterio":"","v1":""}',
            dataType: "json",
            success: function (devolucion) {},
            error: function (req, status, error) {                                    
            }
          });
        }
      },
      error: function (req, status, error) {
        alert("No hubo respuesta desde el servidor. Prueba otra vez.");
      }
    });
  }
}

服务器端处理代码(关键部分)

public string TroceadoFileBase64(string base64file, string nombrefile, string start)
{
    string jsonDevolucion = "";
           
    string base64filedec = HttpUtility.UrlDecode(base64file);  
    string base64filedec1 = HttpUtility.UrlDecode(base64file);  
                                                                               
    byte[] b = null;
    System.Text.ASCIIEncoding codificador = new System.Text.ASCIIEncoding();
    b = codificador.GetBytes(base64filedec1);

    CrearfiledesdeArray(b, nombrefile);

    string[,] devolucion = new string[2, 2];                
    devolucion[0,0] = "nombrefile";
    devolucion[0,1] = nombrefile;
    devolucion[1,0] = "start";
    devolucion[1,1] = start;
                
    jsonDevolucion = JsonConvert.SerializeObject(devolucion);

    return jsonDevolucion;
}
               
public string TroceadoFileBase64_fin(string nombrefile)
{
    string strtextfile = File.ReadAllText((string)HttpContext.Current.Server.MapPath("~") + "google/archivoseditados/" + Left(nombrefile, nombrefile.Length - 4) + ".txt");

    int mod4 = strtextfile.Length % 4;
    if (mod4 > 0)
    {
        strtextfile += new string('=', 4 - mod4);
    }

    byte[] b = null;
    b = Convert.FromBase64String(strtextfile);

    File.WriteAllBytes((string)HttpContext.Current.Server.MapPath("~") + "google/archivoseditados/" + nombrefile, b);

    return "Finalizado";
}

public void CrearfiledesdeArray(Byte[] array, string nombrefile)
{
    FileStream fs = new FileStream((string)HttpContext.Current.Server.MapPath("~") + "google/archivoseditados/" + Left(nombrefile, nombrefile.Length - 4) + ".txt", FileMode.Append);
    fs.Seek(0, SeekOrigin.End);
    fs.Write(array, 0, array.Length);
    fs.Flush();
    fs.Dispose();
}

我已经确认客户端的dataURLto64和服务器读取的strtextfile64内容完全一致,长度也相同,但生成的BMP文件就是格式错误。有没有大佬能帮我找出问题所在?

备注:内容来源于stack exchange,提问作者Manuel Cera Vera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:33:04