簡體   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