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

时间:2013-07-24 21:21:06

标签: javascript asp.net-mvc-4

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

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

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

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

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

}

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

7 个答案:

答案 0 :(得分:6)

现在唯一可行的方法是对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 :(得分:4)

我遇到了同样的问题并经历了很多研发。我得出的结论很少。

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

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

根据我的说法,上面发现的两种方法都很慢。当我发送每个5MB大小的3个文件时,我的浏览器(IE 10浏览器)内存消耗在通过Ajax请求发送数据时呈指数级增长。我仍然无法弄清楚这个问题。如果有人能够使用Ajax发送字节数组,请告诉我。

方法3: 第三种方法是将字节数组转换为base64编码的字符串并发送它。虽然这会使文件大小增加33%,但这种方法远胜于两种方法。我可以轻松发送15 MB文件,浏览器的内存消耗为80MB,发送这3个文件后,一旦发送文件,消耗就会减少。

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

如果我错了,请告诉我。

答案 2 :(得分:1)

我使用以下代码将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; }
}

答案 3 :(得分:0)

将控制器操作更改为接受int[]而不是byte[],然后转换为字节数组。 post值仍然可以是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编码,并将其作为字符串传递。

可能有替代品,如过滤器或属性或类似的东西,但这是我所知道的最简单的方法。

答案 4 :(得分:0)

你必须使用 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
    }

答案 5 :(得分:0)

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

var serialized = fromByteArray(myUint8Array);

fromeByteArray函数来自this github project。我从this documentation on mdn了解了base64-js。

答案 6 :(得分:0)

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

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

这样.Net端点能够反序列化为Byte数组。