【问题标题】:AngularJS GET byte[] error when downloading binary data using ASP.NET Web API使用 ASP.NET Web API 下载二进制数据时 AngularJS GET byte[] 错误
【发布时间】:2014-11-21 11:42:58
【问题描述】:

有关此问题的更多背景信息,请参阅Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API

在开发用于上传/下载字节数组的 TypeScript/AngularJS(v1.2.22)/Web API 解决方案时,我发现 AngularJS 无法正确响应客户端对字节数组数据的 GET 请求。为了证明我的服务器代码,我在 Angular 之外创建了一些单独的 XMLHttpRequest 代码,它们可以与 Web API 服务器代码一起正常工作。

  1. 我在 AngularJS 代码中可能仍然缺少某些东西,但我搜索了许多文档、文章和代码示例,并没有发现任何明显错误的代码。
  2. 我已验证通过 Fiddler 从服务器发送的数据对于 AngularJS 和 XMLHttpRequest 代码是相同的。
  3. Angular 代码的第一个问题是它将数据解释为字符串,而不是字节数组,而 XMLHttpRequest 代码将该代码正确解释为字节数组。
  4. 第二个问题是 AngularJS 代码破坏了所有大于 127 的值(即 128-255)。我在下面附上了一个屏幕截图。
  5. 第三个问题是数据丢失。 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 代码(即,返回具有正确值的 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 字节数组重复测试。同样,图像数据内容(见下文)和长度(27,998 字节)在 Fiddler 中是相同的。

Angular 代码块中接收到的图像必须从字符串转换为字节数组,并且大小要小得多(~20K)。

似乎有两种可能:1)我的 AngularJS 代码不好,或者 2)Angular 有问题。

我将尝试在调试器中深入研究 AngularJS 代码,但我不确定我能走多远。

我真的可以向你们中的一些 Angular 专家寻求帮助。

谢谢...

更新 Eric Eslinger 刚刚指出了我的错误。 arrayBuffer 必须是 arraybuffer(没有骆驼)

【问题讨论】:

    标签: javascript arrays angularjs binary-data


    【解决方案1】:

    具体调用是

    $http.get('http://example.com', {responseType: 'arraybuffer'})
    

    你会得到一个正确的二进制响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-10
      • 2015-07-18
      • 2018-12-28
      • 1970-01-01
      • 2014-11-18
      • 2014-07-27
      • 2016-05-10
      • 1970-01-01
      相关资源
      最近更新 更多