繁体   English   中英

.NET MVC从JSON Uint8Array反序列化字节数组

[英].NET MVC deserialize byte array from JSON Uint8Array

我在客户端Web应用程序上使用js-scrypt( https://github.com/tonyg/js-scrypt )对密码进行哈希处理和加盐处理,然后再将密码发布到服务器端.NET MVC应用程序进行哈希处理和再加盐。 此JavaScript库将字节数组实现为JavaScript Uint8Arrays。 如何获得我的MVC控制器将JSON Uint8Array反序列化为一个字节[]?

JavaScript示例:(AJAX.Post是我编写的库,myUint8Array正确序列化了)

AJAX.Post('www.example.com/SendByteArray', { myByteArray: myUint8Array }, Callback);

C#示例:(在我的默认控制器中)

[HttpPost]
public async Task<JsonResult> SendByteArray(byte[] myByteArray) {

}

在此示例中,myByteArray始终为null。 我已经尝试了几种基于转换为字符串然后返回到byte []的方法,但是我一直无法获得正确的值。 如果我能以某种方式直接将代码直接实现到.NET的JSON反序列化器中,以便上面的代码按原样工作,那将是非常可取的,因为我还有其他一些项目,如果我可以在之间直接传递字节数组,可以做一些很酷的事情服务器端和客户端应用程序。

现在,我唯一可以使用的方法是对Uint8Array进行base64编码,在C#中将其捕获为字符串,然后将该字符串转换为byte []。

JavaScript:

AJAX.Post('www.example.com/SendByteArray', { strByteArray: btoa(String.fromCharCode.apply(null, myUint8Array)) }, Callback);

C#:

[HttpPost]
public async Task<JsonResult> SendByteArray(string strByteArray) {
    byte[] myByteArray = Convert.FromBase64String(strByteArray);
}

经过大量的研发,我面临着同样的问题。 我得出了一些结论。

方法1:C#无法反序列化javascript类型数组(UInt8Array,UInt16Array等)。 数据应该从类型数组复制到普通的Java脚本数组中,并且应该发送该数据。 在接收端(C#端点方法),该参数应为整数数组而不是字节数组。 如果放置了字节数组,则在终点接收到的数据为空。 接收到的整数数组应转换为字节数组以进行文件恢复。

方法2:发送类型化数组数据(而不是将javascript类型化数组数据复制到普通数组中)的另一种方法是按原样发送类型化数组数据,并且在接收端(C#端点方法),方法参数应为对象。 该对象应使用一些linq进行迭代,并应转换为字节数组以进行文件恢复。

根据我的看法,以上两种方法都非常慢。 当我发送3个文件(每个文件大小均为5MB)时,通过Ajax请求发送数据时,浏览器(IE 10浏览器)的内存消耗呈指数增长。 我仍然无法找出问题所在。 如果有人能够使用Ajax发送字节数组,请告诉我。

方法3:第三种方法是将字节数组转换为base64编码的字符串并将其发送。 尽管这将文件大小增加了33%,但此方法远优于以上两种方法。 我可以轻松发送15 MB的文件,并且在发送这3个文件的同时浏览器的内存消耗约为80 MB,一旦发送文件,消耗量就会减少。

重要提示:请在读取文件内容后重新分配变量的内存。 IE中的垃圾收集不是很好。 使用fileReader读取文件后,我遇到了很多内存消耗问题。 不再需要文件时,请取消分配文件中所有未使用的变量和字节数组的内容。

如果有错,请告诉我。

我使用以下代码将大文件从Angular 5批量上载到ASP Core Web API。 在客户端-将ArrayBuffer转换为Base64String:

private arrayBufferToBase64String(buffer: ArrayBuffer) {
  let binaryString = ''
  var bytes = new Uint8Array(buffer);
  for (var i = 0; i < bytes.byteLength; i++) {
    binaryString += String.fromCharCode(bytes[i]);
  }

  return window.btoa(binaryString);
}

发布字符串(这是Angular 2+版本):

var data = {
  data: this.arrayBufferToBase64String(arrayBuffer)
}

this.httpClient.post(url, data)

在服务器(C#)上:

var bytes = Convert.FromBase64String(part.Data);

part是模型类:

public class FilePartModel
{
    public string Data { get; set; }
}

将您的控制器操作更改为接受int[]而不是byte[] ,然后转换为字节数组。 帖子值仍可以是JSON数组。

[HttpPost]
public async Task<JsonResult> SendByteArray(int[] myByteArray) {

     byte[] theBytes = myByteArray.Select(i => (byte)i).ToArray();

     // Or any one of a dozen other ways of converting it

}

为了发布到字节数组,您必须对客户端上的字节进行base-64编码,然后将其作为字符串传递。

可能有其他选择,例如过滤器或属性或类似的东西,但这是我所知道的最简单的方法。

您必须使用Jason.stringify对其进行序列化并设置ajax的某些属性。这是我使用且有效的示例

            var list = [];

           //Fill list array

            var parameters = {};
            parameters = JSON.stringify({ "Your parameter": list });
            jQuery.ajax({
                url: '@Url.Action("Your Action")';,
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                dataType: "html",
                traditional: true,
                data: parameters,
                success: function (data, textStatus, jqXHR) {
                   //TODO: on success
                },
                error: function (data) {
                       //TODO: on fail
                }    
            });

    [HttpPost]
    public async Task<JsonResult> SendByteArray(IEnumerable<byte> myByteArray) {

    }

     OR Do this Way

    [HttpPost]
    public async Task<JsonResult> SendByteArray(int[] myByteArray) {
      convert to byte here
    }

建立在user1084447的解决方案(序列化和反序列化为base64字符串)的基础上,这对于序列化非常有效:

var serialized = fromByteArray(myUint8Array);

fromeByteArray函数来自此github项目 我从mdn上的该文档了解了base64-js。

我无法更改服务器端,因此需要在服务器的端点上保留byte[]类型。 为了解决这个问题,我最终将Uint8Array转换为一个简单的字节数组,JSON将其解析为数组而不是对象。

            const byteArray = [];
            Object.keys(contentUint8Array).forEach((key) =>{
                const byteForKey = contentUint8Array[key];
                byteArray.push(byteForKey);
            });

这样,.Net端点可以反序列化为Byte数组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM