有關此問題的其他背景信息,請參閱Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API。AngularJS使用ASP.NET Web API下載二進制數據時發生GET byte []錯誤
在上載/下載字節數組的TypeScript/AngularJS(v1.2.22)/ Web API解決方案中,我發現了一個場景,其中AngularJS沒有正確響應客戶端GET字節數組數據請求。爲了證明我的服務器代碼,我在Angular之外創建了一些單獨的XMLHttpRequest代碼,它可以與Web API服務器代碼正常工作。
- 可能有東西,我仍然在AngularJS代碼所缺少的,但我已經走遍了許多文件,文章和代碼示例,並沒有發現任何東西,顯然是錯誤的代碼。
- 我已經驗證通過Fiddler從服務器發送的數據對於AngularJS和XMLHttpRequest代碼是相同的。
- Angular代碼的第一個問題是它將數據解釋爲字符串,而不是字節數組,而XMLHttpRequest代碼將該代碼正確解釋爲字節數組。
- 第二個問題是AngularJS代碼破壞所有大於127的值(即128-255)。我包括了下面的這個屏幕截圖。
- 第三個問題是數據丟失。 AngularJS代碼中的重建數據只有217個字節,而不是256個字節。
這是可用的XMLHttpRequest代碼。請注意,該響應是UInt8Array構造函數的有效參數。
var oReq = new XMLHttpRequest();
oReq.open("GET", "/api/Values", true);
// Worked on IE, Chrome, and Firefox with this line commented out, Firefox docs say it should be declared.
oReq.overrideMimeType("charset=x-user-defined");
oReq.responseType = "arraybuffer";
oReq.onload = function() {
var arrayBuffer = oReq.response, bArray = new Uint8Array(arrayBuffer), str = "";
if (arrayBuffer) {
for (var i = 0; i < bArray.length; i++) {
str += bArray[i] + ((i < bArray.length - 1) ? "," : "");
}
window.alert("XMLHttpRequest GET Output: " + str);
}
};
這裏是AngularJS代碼不能正常工作(即返回一個字節[]與正確的值)。請注意,響應必須從字符串轉換爲數組。
$http({
method: 'GET',
url: 'api/values',
headers: {'Content-Type': 'application/octet-stream; charset=x-user-defined'},
// The issue was caused by using camel case B. MUST BE 'arraybuffer'
// Changed code below to reflect correction.
responseType: 'arraybuffer',
transformResponse: []
}).success(function (response, status) {
if (status === 200) {// Issue 1: response is not byte[]. It is a string. Issue 2: String values > 127 are corrupted.
var buffer = new ArrayBuffer(response.length), bArray = new Uint8Array(buffer), len = bArray.length, i, str = "";
for (i = 0; i < len; i++) {// Cannot create an array from response data here, but I can using XMLHttpRequest.
str += bArray[i] = response[i].charCodeAt(0);// Have to read character value.
if (i < len - 1)
str += ",";
}
window.alert("Angular Output: " + str);
var unsigned8Int = new Uint8Array(bArray);// Can create new array here after processing string values.
var b64Encoded = btoa(String.fromCharCode.apply(null, unsigned8Int));
callback(b64Encoded);
}
}).error((data, status) => {
console.log('[ERROR] Status Code:' + status);
});
我註釋了上述AngularJS代碼中的問題。我根據各種文章對上述代碼進行了許多修改,但都沒有成功。我嘗試了默認的transformResponse,但發現有一篇文章說默認值必須重置。
服務器端代碼如下:
[AcceptVerbs("Get")]
public HttpResponseMessage Get()
{
byte[] item = new byte[256];
for (var i = 0; i < item.Length; i++)
{
item[i] = (byte)i;
}
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(item);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
}
我檢查十六進制數據中的Fiddler下面每個測試用例,並且它是相同的(即,000102 ... EFFF),且長度在Fiddler中是256.在Angular代碼中,數據長度只有217和256,所以數據被破壞並丟失。
下面是兩個不同的GET代碼塊的屏幕截圖。
我重複測試與服務器代碼,而不是256字節數組注入的圖像。同樣,在Fiddler中圖像數據內容(見下文)和長度(27,998字節)是相同的。
的角碼塊內的接收到的圖像必須從一個字符串轉換爲一個字節數組,大小爲小得多(〜20K)。
似乎有兩種可能性:1)我的AngularJS代碼不好,或者2)Angular存在問題。
我將嘗試深入調試器中的AngularJS代碼,但我不知道我會得到多遠。
我真的可以用這個從你們中的一些人的幫助角運動員。
謝謝...
更新埃裏克Eslinger只是指出我的錯誤。 arrayBuffer必須arraybuffer BE(無駱駝)