unity就是将图片转base64通过json在网络传输到服务器后convert.frombase64后不一致了C#用 JSON序列化图片

其他协议都没有问题 就是将图片转base64通过json在网络传输到服务器后convert.frombase64后不一致了 本机上运行服务器和客户端没问题其他数据也能准确得到 但是其他机器做客户端除了base64都可以识别 是不是网络传输对于json转base64有长度限制 超过一定长度就发送不了了

using System;
using UnityEngine;
using System.Linq;

public class MsgBase{
    public string protoName = "null";
    //编码
    public static byte[] Encode(MsgBase msgBase){
        string s = JsonUtility.ToJson(msgBase); 
        return System.Text.Encoding.UTF8.GetBytes(s);
    }

    //解码
    public static MsgBase Decode(string protoName, byte[] bytes, int offset, int count){
        string s = System.Text.Encoding.UTF8.GetString(bytes, offset, count);
        MsgBase msgBase = (MsgBase)JsonUtility.FromJson(s, Type.GetType(protoName));
        return msgBase;
    }

    //编码协议名(2字节长度+字符串)
    public static byte[] EncodeName(MsgBase msgBase){
        //名字bytes和长度
        byte[] nameBytes = System.Text.Encoding.UTF8.GetBytes(msgBase.protoName);
        Int16 len = (Int16)nameBytes.Length;
        //申请bytes数值
        byte[] bytes = new byte[2+len];
        //组装2字节的长度信息
        bytes[0] = (byte)(len%256);
        bytes[1] = (byte)(len/256);
        //组装名字bytes
        Array.Copy(nameBytes, 0, bytes, 2, len);

        return bytes;
    }

    //解码协议名(2字节长度+字符串)
    public static string DecodeName(byte[] bytes, int offset, out int count){
        count = 0;
        //必须大于2字节
        if(offset + 2 > bytes.Length){
            return "";
        }
        //读取长度
        Int16 len = (Int16)((bytes[offset+1] << 8 )| bytes[offset] );
        //长度必须足够
        if(offset + 2 + len > bytes.Length){
            return "";
        }
        //解析
        count = 2+len;
        string name = System.Text.Encoding.UTF8.GetString(bytes, offset+2, len);
        return name;
    }
}



```c#
using System;
using UnityEngine;
using System.Linq;

public class MsgBase{
    public string protoName = "null";
    //编码
    public static byte[] Encode(MsgBase msgBase){
        string s = JsonUtility.ToJson(msgBase); 
        return System.Text.Encoding.UTF8.GetBytes(s);
    }

    //解码
    public static MsgBase Decode(string protoName, byte[] bytes, int offset, int count){
        string s = System.Text.Encoding.UTF8.GetString(bytes, offset, count);
        MsgBase msgBase = (MsgBase)JsonUtility.FromJson(s, Type.GetType(protoName));
        return msgBase;
    }

    //编码协议名(2字节长度+字符串)
    public static byte[] EncodeName(MsgBase msgBase){
        //名字bytes和长度
        byte[] nameBytes = System.Text.Encoding.UTF8.GetBytes(msgBase.protoName);
        Int16 len = (Int16)nameBytes.Length;
        //申请bytes数值
        byte[] bytes = new byte[2+len];
        //组装2字节的长度信息
        bytes[0] = (byte)(len%256);
        bytes[1] = (byte)(len/256);
        //组装名字bytes
        Array.Copy(nameBytes, 0, bytes, 2, len);

        return bytes;
    }

    //解码协议名(2字节长度+字符串)
    public static string DecodeName(byte[] bytes, int offset, out int count){
        count = 0;
        //必须大于2字节
        if(offset + 2 > bytes.Length){
            return "";
        }
        //读取长度
        Int16 len = (Int16)((bytes[offset+1] << 8 )| bytes[offset] );
        //长度必须足够
        if(offset + 2 + len > bytes.Length){
            return "";
        }
        //解析
        count = 2+len;
        string name = System.Text.Encoding.UTF8.GetString(bytes, offset+2, len);
        return name;
    }
}






Texture2D texture = /* 你的纹理 */;
byte[] imageBytes = texture.EncodeToPNG();
string base64Image = Convert.ToBase64String(imageBytes);

```

据我了解,这个问题可能是因为您的 base64 字符串中的特殊字符被替换了,例如 + 被替换成空格。这可能会导致上传的图片不完整1。您可以尝试使用以下方法解决此问题:
1.将 base64 字符串中的特殊字符替换回来,例如将空格替换为 +。
2.将 base64 字符串转换为字节数组,然后使用字节数组创建 Texture2D 对象
给你一个示例:

string base64String = "your base64 string";
base64String = base64String.Replace(" ", "+");
byte[] bytes = Convert.FromBase64String(base64String);
Texture2D texture = new Texture2D(1, 1);
texture.LoadImage(bytes);

1、检查下传输的数据与图片一致,例如图像大小,分辨率,编码等。因为使用不同压缩格式的图片的编码长度可能不同,所以需要确保传输的数据与原始图片一致。
2、检查下传输过程中有没有出现数据丢失或损坏的情况。如果数据在传输过程中受到干扰或损坏,也会导致无法正确解码的问题
3、尝试换一种解码方式,检查将Base64编码的字符串转换为图像时,是否使用了正确的解码方法

可以借鉴下

public ActionResult UploadSignature2(string src_data)
    {
      Class1.Base64StrToImage(src_data, "C:\\Users\\45448\\Desktop\\1\\"+ DateTime.Now.ToString("yyyyMMddHHss") + ".png");
      return Json(1, JsonRequestBehavior.AllowGet);
    }
 
    /// <summary>
    /// 将Base64字符串转换为图片并保存到本地
    /// </summary>
    /// <param name="base64Str">base64字符串
    /// <param name="savePath">图片保存地址,如:/Content/Images/10000.png
    /// <returns></returns>
    public static bool Base64StrToImage(string base64Str, string savePath)
    {
      var ret = true;
      try
      {
        base64Str = base64Str.Replace("data:image/png;base64,", "").Replace("data:image/jgp;base64,", "")
          .Replace("data:image/jpg;base64,", "").Replace("data:image/jpeg;base64,", ""); //将base64头部信息替换
        var bitmap = Base64StrToImage(base64Str);
        if (bitmap != null)
        {
          //创建文件夹
          var folderPath = savePath.Substring(0, savePath.LastIndexOf('\\'));
          ////FileHelper.CreateDir(folderPath);
          if (!Directory.Exists(folderPath))
          {
            Directory.CreateDirectory(folderPath);
          }
          //图片后缀格式
          var suffix = savePath.Substring(savePath.LastIndexOf('.') + 1,
            savePath.Length - savePath.LastIndexOf('.') - 1).ToLower();
          var suffixName = suffix == "png"
            ? ImageFormat.Png
            : suffix == "jpg" || suffix == "jpeg"
              ? ImageFormat.Jpeg
              : suffix == "bmp"
                ? ImageFormat.Bmp
                : suffix == "gif"
                  ? ImageFormat.Gif
                  : ImageFormat.Jpeg;
 
          //这里复制一份对图像进行保存,否则会出现“GDI+ 中发生一般性错误”的错误提示
          var bmpNew = new Bitmap(bitmap);
          bmpNew.Save(savePath, suffixName);
          bmpNew.Dispose();
          bitmap.Dispose();
        }
        else
        {
          ret = false;
        }
      }
      catch (Exception ex)
      {
        ret = false;
      }
      return ret;
   
    }
?
/// <summary>
    /// Image 转成 base64
    /// </summary>
    /// <param name="fileFullName">
    public static string ImageToBase64(string fileFullName)
    {
      try
      {
        Bitmap bmp = new Bitmap(fileFullName);
        MemoryStream ms = new MemoryStream();
        var suffix = fileFullName.Substring(fileFullName.LastIndexOf('.') + 1,
          fileFullName.Length - fileFullName.LastIndexOf('.') - 1).ToLower();
        var suffixName = suffix == "png"
          ? ImageFormat.Png
          : suffix == "jpg" || suffix == "jpeg"
            ? ImageFormat.Jpeg
            : suffix == "bmp"
              ? ImageFormat.Bmp
              : suffix == "gif"
                ? ImageFormat.Gif
                : ImageFormat.Jpeg;
 
        bmp.Save(ms, suffixName);
        byte[] arr = new byte[ms.Length]; ms.Position = 0;
        ms.Read(arr, 0, (int)ms.Length); ms.Close();
        return Convert.ToBase64String(arr);
      }
      catch (Exception ex)
      {
        return null;
      }
    }

网络传输对于json转base64没有固定长度限制,理论上可以传输任意长度的base64字符串。因此,您遇到的问题可能与网络传输无关。

通过您提供的信息,可能有以下一些原因会导致图片转base64后在服务器端解码不一致:

  1. 图片被损坏:

如果您从客户端传输的图片数据损坏,可能会导致编码后的base64字符串与原始图片数据不一致。您可以通过比较客户端和服务器端图片数据的哈希值来检查是否存在数据损坏。

  1. 字符编码问题:

在将base64字符串转化为二进制数据时,需要确保使用相同的字符编码,否则可能导致解码后的二进制数据不一致。您可以在客户端和服务器端都使用相同的字符编码来解决这个问题。

  1. JSON格式不正确:

在将base64字符串打包为JSON字符串时,需要确保JSON格式正确,否则可能导致解码错误。您可以使用JSON解析器来检查JSON格式是否正确。

  1. 字符串截断:

如果您的base64字符串非常长,可能会存在在传输过程中被截断的情况。这可能是由于网络传输不稳定或传输过程中的缓冲区大小限制造成的。确保缓冲区大小足够大,并使用TCP协议进行传输可以解决这个问题。

这里提供一份示例代码,用于将图片转化为base64字符串并打包为JSON字符串:


```c
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment (lib, "Ws2_32.lib")
using namespace std;
 // 将文件转化为base64字符串
string fileToBase64(const string& fileName) {
    // 读取文件数据
    ifstream ifs(fileName, ios::binary | ios::ate);
    ifstream::pos_type pos = ifs.tellg();
    vector<char> fileBytes(pos);
    ifs.seekg(0, ios::beg);
    ifs.read(fileBytes.data(), pos);
    ifs.close();
    // 转化为base64字符串
    string base64;
    const char* base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    size_t fileSize = fileBytes.size();
    size_t i = 0;
    while (i < fileSize) {
        // 读取三个字节
        uint32_t buffer = 0;
        if (i + 2 < fileSize) {
            buffer = (fileBytes[i] << 16) | (fileBytes[i + 1] << 8) | fileBytes[i + 2];
        }
        else {
            buffer = (fileBytes[i] << 16);
            if (i + 1 < fileSize) {
                buffer |= (fileBytes[i + 1] << 8);
            }
        }
        // 转化为四个base64字符
        base64 += base64Table[(buffer >> 18) & 0x3F];
        base64 += base64Table[(buffer >> 12) & 0x3F];
        base64 += (i + 1 < fileSize) ? base64Table[(buffer >> 6) & 0x3F] : '=';
        base64 += (i + 2 < fileSize) ? base64Table[buffer & 0x3F] : '=';
        i += 3;
    }
    return base64;
}
 // 打包为JSON字符串
string packageToJson(const string& base64) {
    stringstream ss;
    ss << "{\"image\":\"" << base64 << "\"}";
    return ss.str();
}
 int main(int argc, char** argv) {
    // 初始化WinSock
    WSADATA wsaData;
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        cerr << "WSAStartup failed: " << result << endl;
        return 1;
    }
    // 连接服务器
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (clientSocket == INVALID_SOCKET) {
        cerr << "socket failed: " << WSAGetLastError() << endl;
        WSACleanup();
        return 1;
    }
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(12345);
    inet_pton(AF_INET, "127.0.0.1", &(serverAddr.sin_addr));
    result = connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
    if (result == SOCKET_ERROR) {
        cerr << "connect failed: " << WSAGetLastError() << endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }
    // 发送图片数据
    string base64 = fileToBase64("test.jpg");
    string json = packageToJson(base64);
    result = send(clientSocket, json.c_str(), json.size(), 0);
    if (result == SOCKET_ERROR) {
        cerr << "send failed: " << WSAGetLastError() << endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }
    cout << "send " << result << " bytes data" << endl;
    // 关闭套接字
    closesocket(clientSocket);
    WSACleanup();
    return 0;
}

```

弄张小图,把上传的json贴出来看看

JSON格式在数据传输时有一个长度限制,一旦超过限制就会导致数据丢失或损坏,可以通过使用其他数据传输格式解决,例如二进制。将图像数据直接转换为原始二进制格式,并将其作为分块字节流发送