2014-09-23 39 views
12

我花了好几天的时间研究和研究上传/下载byte []的解决方案。我很接近,但有一个似乎在AngularJS代码块中的问题。使用AngularJS和ASP.NET Web API上传/下载字节数组

在SO上有类似的问题,但它没有任何回应。请参阅https://stackoverflow.com/questions/23849665/web-api-accept-and-post-byte-array

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

  1. 我正在尝试创建一个通用客户端/服务器接口来上传和下载byte [],这些接口用作专有服务器数据库的一部分。
  2. 我在客户端上使用TypeScript,AngularJS,JavaScript和Bootstrap CSS来创建单页面应用程序(SPA)。
  3. 我在服务器上使用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

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

    • 由不正确的,我指的是错误的大小(〜10K与〜27.5K),这是不确认为UintArray构造有效值。当我将光标放在下面客户端代码中显示的返回“响应”上时,Visual Studio显示JFIF,但没有其他可见的内容指示器。

/**********************服务器代码**************** ********/ 添加缺失的项目后[FromBody]字节[]

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十六进制数据显示256个字节,值范围从00,01,...,EF,FF,这是正确的。正如我前面提到的,我可以返回一个图像并在Fiddler中正确地查看它,所以Web API服务器接口对于POST和GET都适用。

我想香草XMLHttpRequest看到我可以得到在AngularJS环境以外的工作。

XMLHttpRequest的测试更新

我已经能够证实,香草XMLHttpRequest的工作原理与服务器的GET和能够返回正确的字节代码和测试图像。

好消息是我可以绕过AngularJS来让我的系统工作,但坏消息是我不喜欢这样做。我宁愿与Angular保持所有客户端服务器通信。

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

更新

埃里克Eslinger在谷歌网上论坛给我发了一个小的代码段突出显示的responseType应该是“arraybuffer”,全部小写。我更新了上面的代码块以显示小写值并添加了一个注释。

谢谢...

+0

你能在类似的问题,建议我有[问题] [1] [1]:http://stackoverflow.com/questions/31612259/sending-byte-collections-with-form- form-data-to-api-using-angularjs – 2015-07-25 09:53:33

回答

11

我终于收到了从埃里克Eslinger在谷歌集团的响应。他指出他使用

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

他提到camelcase可能是重要的,这是。改变了一个角色,现在整个流程都在工作。

所有荣誉都归埃里克埃斯林格所有。

+0

我使用自定义get,但是这个responseType:'arraybuffer'救了我,谢谢分享! – SomeRandomName 2014-12-04 15:13:29

+0

我收到一个TypedArray构造函数参数是无效的错误,这只是因为我有'arrayBuffer'。将它更改为'arraybuffer',并且嘿presto错误消失了!向Eric表示敬意。 – 2016-06-03 14:32:30

相关问题