[英].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.