使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组

Posted

技术标签:

【中文标题】使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组【英文标题】:Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API 【发布时间】:2014-11-18 06:50:12 【问题描述】:

我花了几天时间研究和研究上传/下载 byte[] 的解决方案。我很接近,但还有一个问题似乎在我的 AngularJS 代码块中。

关于 SO 有一个类似的问题,但没有回复。见https://***.com/questions/23849665/web-api-accept-and-post-byte-array

在我陈述我的问题之前,这里有一些背景信息来设置上下文。

    我正在尝试创建一个通用客户端/服务器接口来上传和下载字节 [],它们用作专有服务器数据库的一部分。 我在客户端使用 TypeScript、AngularJS、javascript 和 Bootstrap CSS 来创建单页应用 (SPA)。 我在服务器上使用 ASP.NET Web API/C#。

正在开发 SPA 以替换在 Silverlight 中开发的现有产品,因此它受限于现有系统要求。 SPA 还需要针对广泛的设备(移动设备到桌面设备)和主要操作系统。

在几个在线资源(如下所列)的帮助下,我的大部分代码都能正常工作。我正在使用下面 Byte Rot 链接中的 byte[] 的异步多媒体格式化程序。

http://byterot.blogspot.com/2012/04/aspnet-web-api-series-part-5.html

Returning binary file from controller in ASP.NET Web API

    我在客户端使用转换为 Uint8Array 的 jpeg 作为我的测试用例。 实际的系统字节数组将包含压缩到预定义数据包中的混合内容。但是,我需要能够处理任何有效的字节数组,因此图像是有效的测试用例。 使用下面显示的客户端和服务器代码以及 Byte Rot Formatter(未显示,但在其网站上提供)将数据正确传输到服务器。 我已验证 jpeg 已在服务器上正确接收为 byte[] 以及字符串参数元数据。 我已使用 Fiddler 验证是否将正确的响应发送回客户端。 大小正确 图片可在 Fiddler 中查看。

    我的问题是下面显示的Angular客户端代码中的服务器响应不正确。

    不正确是指错误的大小(~10K 对~27.5K),它不被识别为 UintArray 构造函数的有效值 .当我将光标放在下面客户端代码中显示的返回“响应”上时,Visual Studio 会显示 JFIF,但没有其他可见的内容指示符。

/********************** 服务器代码 ********************** **/ 在 [FromBody]byte[]

之后向代码添加了缺失项
public class ItemUploadController : ApiController 
[AcceptVerbs("Post")]
    public HttpResponseMessage Upload(string var1, string var2, [FromBody]byte[] item)
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(item);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        return result;
    

/********************** 示例客户端代码 ********************/

我在代码中唯一省略的是实际的变量参数。

$http(
url: 'api/ItemUpload/Upload',
    method: 'POST',
    headers:  'Content-Type': 'application/octet-stream' ,// Added per Byte Rot blog...
    params: 
        // Other params here, including string metadata about uploads
        var1: var1,
        var2: var2
    ,
data: new Uint8Array(item),
// arrybuffer must be lowecase. Once changed, it fixed my problem.
responseType: 'arraybuffer',// Added per http://www.html5rocks.com/en/tutorials/file/xhr2/
transformRequest: [],
)
.success((response, status) => 
    if (status === 200) 
        // The response variable length is about 10K, whereas the correct Fiddler size is ~27.5K.
        // The error that I receive here is that the constructor argument in invalid.
        // My guess is that I am doing something incorrectly with the AngularJS code, but I
        // have implemented everything that I have read about. Any thoughts???
        var unsigned8Int = new Uint8Array(response);
        // For the test case, I want to convert the byte array back to a base64 encoded string
        // before verifying with the original source that was used to generate the byte[] upload.
        var b64Encoded = btoa(String.fromCharCode.apply(null, unsigned8Int));
        callback(b64Encoded);
    
)
.error((data, status) => 
    console.log('[ERROR] Status Code:' + status);
);

/**************************************************** ******************/

任何帮助或建议将不胜感激。

谢谢...

已编辑以包含更多诊断数据

首先,我使用 angular.isArray 函数确定响应值不是数组,我认为它应该是。

其次,我使用以下代码来询问响应,它似乎是一个不可见的字符串。前导字符似乎与图像字节数组代码中的任何有效序列都不对应。

var buffer = new ArrayBuffer(response.length);
var data = new Uint8Array(buffer);
var len = data.length, i;
for (i = 0; i < len; i++) 
    data[i] = response[i].charCodeAt(0);

实验结果

我通过在下载的服务器上创建 0 到 255 的字节数组值来运行实验。 AngularJS 客户端正确接收了前 128 个字节(即 0,1,...,126,127),但其余值在 Internet Explorer 11 中为 65535,在 Chrome 和 Firefox 中为 65533。 Fiddler 显示通过网络发送了 256 个值,但在 AngularJS 客户端代码中只收到了 217 个字符。如果我只使用 0-127 作为服务器值,一切似乎都正常。我不知道是什么原因造成的,但客户端响应似乎更符合有符号字节,我认为这是不可能的。

来自服务器的 Fiddler Hex 数据显示 256 字节,值范围为 00,01,...,EF,FF,这是正确的。正如我之前提到的,我可以返回一个图像并在 Fiddler 中正确查看它,因此 Web API 服务器接口适用于 POST 和 GET。

我正在尝试 vanilla XMLHttpRequest 看看我可以在 AngularJS 环境之外让它工作。

XMLHttpRequest 测试更新

我已经能够确认 vanilla XMLHttpRequest 与服务器一起使用 GET 并且能够返回正确的字节码和测试图像。

好消息是我可以绕过 AngularJS 来让我的系统正常工作,但坏消息是我不喜欢这样做。我更愿意继续使用 Angular 进行所有客户端服务器通信。

我将在 Stack Overflow 上打开一个单独的问题,该问题仅处理我在使用 AngularJS 时遇到的 GET byte[] 问题。如果我能得到解决方案,我将使用该解决方案更新此问题以用于历史目的以帮助其他人。

更新

Google Groups 上的 Eric Eslinger 给我发了一个小代码段,强调 responseType 应该是“arraybuffer”,全部小写。我更新了上面的代码块以显示小写值并添加了注释。

谢谢...

【问题讨论】:

您能否就我遇到的类似问题提出建议[问题][1] [1]:***.com/questions/31612259/… 【参考方案1】:

我终于在 Google Group 上收到了 Eric Eslinger 的回复。他指出他使用

$http.get('http://example.com/bindata.jpg', responseType: 'arraybuffer').

他提到骆驼箱可能很重要,确实如此。更改了一个字符,整个流程现在可以正常工作了。

所有功劳归功于 Eric Eslinger。

【讨论】:

我使用自定义获取,但这个 responseType: 'arraybuffer' 救了我 感谢分享! 我收到 TypedArray 构造函数参数无效错误,这仅仅是因为我有“arrayBuffer”。将其更改为“arraybuffer”,然后错误消失了!确实赞美埃里克。

以上是关于使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS + ASP.NET Web API + ASP.NET MVC 身份验证

ASP.NET WebAPI2 和 AngularJS

使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组

使用angularjs的asp net用户控件

移动浏览器上的 AngularJS 和 ASP.Net WebAPI 社交登录

将Asp.Net WebAPI从AngularJS App的Asp.Net MVC站点移动到一个单独的站点