[英]Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API
[英]AngularJS GET byte[] error when downloading binary data using ASP.NET Web API
有关此问题的其他背景信息,请参见使用AngularJS和ASP.NET Web API上传/下载字节数组 。
在处理用于上载/下载字节数组的TypeScript / AngularJS(v1.2.22)/ Web API解决方案时,我发现AngularJS无法正确响应客户端对字节数组数据的GET请求的情况。 为了证明我的服务器代码,我在Angular之外创建了一些单独的XMLHttpRequest代码,它们可以与Web API服务器代码一起正常工作。
这是有效的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代码(即,返回具有正确值的byte [])。 请注意,响应必须从字符串转换为数组。
$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字节)相同。
Angular代码块内收到的图像必须从字符串转换为字节数组,并且大小要小得多(约20K)。
似乎有两种可能:1)我的AngularJS代码不好,或者2)Angular存在问题。
我将尝试在调试器中深入研究AngularJS代码,但是我不确定我能走多远。
我真的可以从一些Angular笑话中获得帮助。
谢谢...
更新Eric Eslinger刚刚指出了我的错误。 arrayBuffer必须是arraybuffer(没有骆驼)
具体拨打电话是
$http.get('http://example.com', {responseType: 'arraybuffer'})
然后您将获得适当的二进制响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.