2014-09-26 4 views
2

이 문제점에 대한 추가 배경 정보는 Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API을 참조하십시오.ASP.NET Web API를 사용하여 이진 데이터를 다운로드 할 때 AngularJS GET byte [] 오류

Upload/Download 바이트 배열을위한 TypeScript/AngularJS (v1.2.22)/Web API 솔루션을 작업하면서 AngularJS가 바이트 배열 데이터에 대한 클라이언트 측 GET 요청에 올바르게 응답하지 않는 시나리오를 발견했습니다. 내 서버 코드를 증명하기 위해 Web API 서버 코드에서 제대로 작동하는 Angular 외부에 별도의 XMLHttpRequest 코드를 만들었습니다.

  1. AngularJS 코드에는 아직 누락 된 것이있을 수 있지만 많은 문서, 기사 및 코드 예제를 훑어보고 코드에 오류가있는 것은 발견하지 못했습니다.
  2. 필자는 AngularJS 및 XMLHttpRequest 코드에서 Fiddler를 통해 서버에서 보낸 데이터가 동일하다는 것을 확인했습니다.
  3. Angular 코드의 첫 번째 문제는 XMLHttpRequest 코드가 해당 코드를 올바르게 바이트 배열로 해석하는 동안 바이트 배열이 아닌 문자열로 데이터를 해석한다는 것입니다.
  4. 두 번째 문제는 AngularJS 코드가 127보다 큰 모든 값 (예 : 128-255)을 손상시키는 것입니다. 나는 이것의 스크린 샷을 아래에 포함시켰다.
  5. 세 번째 문제는 데이터가 손실된다는 것입니다. AngularJS 코드의 재구성 된 데이터는 256 바이트 대신 217 바이트 만있었습니다.

다음은 작동하는 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 코드입니다. 응답은 문자열에서 배열로 변환되어야합니다.

$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 시도했지만 기본값을 다시 설정해야했다 한 기사를 발견했습니다.

서버 측 코드는 다음과 같다 : I는 아래 각 테스트 케이스에 대한 피들러의 헥스 데이터를 체크하고 (즉, 000,102 ... EFFF) 동일이고, 길이

[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의 경우 256이었습니다. Angular 코드에서 데이터 길이는 256에 비해 217 이었으므로 데이터가 손상되어 손실되었습니다.

다음은 위의 두 가지 다른 GET 코드 블록의 두 가지 스크린 샷입니다.

Screen Shots

난 서버 코드 대신에 256 바이트의 배열에 주입 된 이미지와 시험을 반복했다. 다시, 이미지 데이터 내용 (아래 참조)과 길이 (27,998 바이트)는 Fiddler에서 동일했습니다.

GET Image Response

각 코드 블록 내의 수신 된 이미지는 바이트 배열 문자열에서 변환 할 수 있었고, 크기 (~ 20K) 훨씬 작았 다.

두 가지 가능성이있는 것 같습니다. 1) 내 AngularJS 코드가 좋지 않거나 2) 각도에 문제가 있습니다.

디버거에서 AngularJS 코드로 다이빙을 시도하지만 얼마나 멀리 얻을 수 있는지 잘 모르겠습니다.

저는 여러분 중 몇 분께 도움을받을 수 있습니다. 업데이트 에릭 Eslinger 그냥 내 오류를 지적

감사합니다 .... arrayBuffer 만들 수

답변

4

특정 호출이

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

입니다 (더 낙타) arraybuffer 없어야합니다 그리고 당신은 적절한 이진 응답을 얻을 것이다.