[英].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
}
我无法更改服务器端,因此需要在服务器的端点上保留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.