使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组 [英] Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API

查看:21
本文介绍了使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have spent several days researching and working on a solution for uploading/downloading byte[]’s. I am close, but have one remaining issue that appears to be in my AngularJS code block.

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

There is a similar question on SO, but it has no responses. See https://stackoverflow.com/questions/23849665/web-api-accept-and-post-byte-array

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

Here is some background information to set the context before I state my problem.

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

正在开发 SPA 以取代在 Silverlight 中开发的现有产品,因此它仅限于现有系统要求.SPA 还需要面向广泛的设备(移动到桌面)和主要操作系统.

The SPA is being developed to replace an existing product that was developed in Silverlight so it is constrained to existing system requirements. The SPA also needs to target a broad range of devices (mobile to desktop) and major OSs.

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

With the help of several online resources (listed below), I have gotten most of my code working. I am using an asynchronous multimedia formatter for byte[]’s from the Byte Rot link below.

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

从 ASP.NET 中的控制器返回二进制文件网页 API

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

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

  • 不正确,我的意思是错误的大小(~10K 对 ~27.5K),并且它未被识别为 UintArray 构造函数的有效值.当我将光标放在下面客户端代码中显示的返回响应"上时,Visual Studio 会显示 JFIF,但没有其他可见的内容指示符.
  • By incorrect, I mean the wrong size (~10K versus ~27.5K) and it is not recognized as a valid value for the UintArray constructor. Visual Studio shows JFIF when I place the cursor over the returned "response" shown in the client code below, but there is no other visible indicator of the content.

/************************ 服务器代码**************************/在 [FromBody]byte[] 之后的代码中添加了缺失的项目

/********************** Server Code ************************/ Added missing item to code after [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;
    }
}

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

/***************** Example Client Code ********************/

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

The only thing that I have omitted from the code are the actual variable parameters.

$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);
});

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

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

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

Any help or suggestions would be greatly appreciated.

谢谢...

编辑以包含更多诊断数据

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

First, I used the angular.isArray function to determine that the response value is NOT an array, which I think it should be.

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

Second, I used the following code to interrogate the response, which appears to be an invisible string. The leading characters do not seem to correspond to any valid sequence in the image byte array code.

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 作为服务器值,一切似乎都正常.我不知道是什么导致了这种情况,但客户端响应似乎更符合签名字节,我认为这是不可能的.

I ran an experiment by creating byte array values from 0 - 255 on the server, which I downloaded. The AngularJS client received the first 128 bytes correctly (i.e., 0,1,...,126,127), but the remaining values were 65535 in Internet Explorer 11, and 65533 in Chrome and Firefox. Fiddler shows that 256 values were sent over the network, but there are only 217 characters received in the AngularJS client code. If I only use 0-127 as the server values, everything seems to work. I have no idea what can cause this, but the client response seems more in line with signed bytes, which I do not think is possible.

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

Fiddler Hex data from the server shows 256 bytes with the values ranging from 00,01,...,EF,FF, which is correct. As I mentioned earlier, I can return an image and view it properly in Fiddler, so the Web API server interface works for both POST and GET.

我正在尝试使用 vanilla XMLHttpRequest 来查看我可以在 AngularJS 环境之外使用它.

I am trying vanilla XMLHttpRequest to see I can get that working outside of the AngularJS environment.

XMLHttpRequest 测试更新

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

I have been able to confirm that vanilla XMLHttpRequest works with the server for the GET and is able to return the correct byte codes and the test image.

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

The good news is that I can hack around AngularJS to get my system working, but the bad news is that I do not like doing this. I would prefer to stay with Angular for all my client-side server communication.

我将在 Stack Overflow 上开一个单独的问题,它只处理我在 AngularJS 中遇到的 GET byte[] 问题.如果我能得到解决方案,我会用解决方案更新这个问题,用于历史目的,以帮助他人.

I am going to open up a separate issue on Stack Overflow that only deals with the GET byte[] issues that I am have with AngularJS. If I can get a resolution, I will update this issue with the solution for historical purposes to help others.

更新

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

Eric Eslinger on Google Groups sent me a small code segment highlighting that responseType should be "arraybuffer", all lower case. I updated the code block above to show the lowercase value and added a note.

谢谢...

推荐答案

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

I finally received a response from Eric Eslinger on Google Group. He pointed out that he uses

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

他提到驼峰驼可能很重要,确实如此.更改了一个字符,现在整个流程都在运行.

He mentioned that the camelcase was probably significant, which it is. Changed one character and the entire flow is working now.

所有功劳都归功于 Eric Eslinger.

All credit goes to Eric Eslinger.

这篇关于使用 AngularJS 和 ASP.NET Web API 上传/下载字节数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆