【问题标题】:.NET MVC deserialize byte array from JSON Uint8Array.NET MVC 从 JSON Uint8Array 反序列化字节数组
【发布时间】:2013-07-24 21:21:06
【问题描述】:

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

【问题讨论】:

    标签: javascript asp.net-mvc-4


    【解决方案1】:

    目前我唯一可以使用的方法是对 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);
    }
    

    【讨论】:

      【解决方案2】:

      经过大量研发后,我也遇到了同样的问题。我得出的结论很少。

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

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

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

      方法 3: 第三种方法是将字节数组转换为 base64 编码的字符串并发送。尽管这将文件大小增加了 33%,但这种方法比上述两种方法要好得多。我可以轻松发送 15 MB 的文件,发送这 3 个文件时浏览器的内存消耗约为 80MB,发送文件后消耗会减少。

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

      如果有误,请告诉我。

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

          【解决方案4】:

          将您的控制器操作更改为接受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 编码,并将其作为字符串传递。

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

          【讨论】:

          • int[] 仍然没有捡起它,它仍然是空的。我认为问题在于 Uint8Array 不会序列化为实际的 JSON 数组,它会序列化为具有 {0: 168, 1: 49,...} 属性以及其他一些属性的对象。
          • 这很有趣 - 没有意识到 Uint8Array 序列化为常规对象而不是直接数组。看起来您是否可以通过调用myUnit8Array.subarray()Uint8Array 转换为常规数组,这应该只为您提供字节,然后您可以将其发布到int[] 参数中。可能值得将它与您的 base-64 解决方案进行比较,看看哪一个提供的占用空间更小。
          • myUnit8Array.subarray() 似乎仍然产生相同的奇数对象 {0: 168, 1: 49,...}
          • @blaster 嗯,以前没看到 - 我猜我的浏览器控制台欺骗了我。我能想到的唯一一件事就是创建一个全新的数组并将所有值一次推入其中,然后序列化该新数组。
          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              基于 user1084447 的解决方案(序列化和反序列化为 base64 字符串),这非常适合序列化:

              var serialized = fromByteArray(myUint8Array);
              

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2019-08-06
                • 1970-01-01
                • 2023-03-14
                • 1970-01-01
                • 2011-09-29
                • 1970-01-01
                相关资源
                最近更新 更多