Я провел несколько дней, исследуя и работая над решением для загрузки/загрузки байта [] s. Я близок, но имею одну оставшуюся проблему, которая, кажется, находится в моем блоке кода AngularJS.
Есть аналогичный вопрос о SO, но он не имеет ответов. См. https://stackoverflow.com/info/23849665/web-api-accept-and-post-byte-array
Вот некоторая справочная информация для установки контекста, прежде чем я укажу свою проблему.
- Я пытаюсь создать клиентский/серверный интерфейс общего назначения для загрузки и загрузки байтов [] s, которые используются как часть запатентованной базы данных сервера.
- Я использую TypeScript, AngularJS, JavaScript и Bootstrap CSS для создания одностраничного приложения (SPA).
- Я использую ASP.NET Web API/С# на сервере.
SPA разрабатывается для замены существующего продукта, который был разработан в Silverlight, поэтому он ограничен существующими системными требованиями. SPA также должен ориентироваться на широкий спектр устройств (мобильных на настольные) и основных ОС.
С помощью нескольких онлайн-ресурсов (перечисленных ниже) я получил большую часть моего кода. Я использую асинхронный мультимедийный форматтер для байта [] s из ссылки Byte Rot ниже.
http://byterot.blogspot.com/2012/04/aspnet-web-api-series-part-5.html
Возврат двоичного файла с контроллера в веб-API ASP.NET
- Я использую jpeg, преобразованный в Uint8Array, как мой тестовый пример на клиенте.
- Реальные системные массивы байтов будут содержать смешанный контент, сжатый в предопределенные пакеты данных. Тем не менее, мне нужно иметь возможность обрабатывать любой действительный массив байтов, поэтому изображение является допустимым тестовым случаем.
- Данные передаются на сервер правильно, используя код клиента и сервера, показанный ниже. И Батарейщик Rotter (не показан, но доступен на их веб-сайте).
- Я проверил, что jpeg получен правильно на сервере в виде байта [] вместе с метаданных параметров строки.
- Я использовал 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), но остальные значения были 65535 в Internet Explorer 11 и 65533 в Chrome и Firefox. Fiddler показывает, что 256 значений были отправлены по сети, но в коде клиента AngularJS имеется только 217 символов. Если я использую только 0-127 в качестве значений сервера, все работает. Я понятия не имею, что может вызвать это, но ответ клиента больше соответствует подписанным байтам, что, я думаю, не возможно.
Данные Fiddler Hex с сервера отображают 256 байтов со значениями от 00,01,..., EF, FF, что является правильным. Как я упоминал ранее, я могу вернуть изображение и правильно его просмотреть в Fiddler, поэтому интерфейс веб-интерфейса API работает как для POST, так и для GET.
Я пытаюсь использовать XMLHttpRequest ваниль, чтобы увидеть, что я могу заставить это работать вне среды AngularJS.
Обновление тестирования XMLHttpRequest
Я смог подтвердить, что vanilla XMLHttpRequest работает с сервером для GET и способен возвращать правильные байтовые коды и тестовое изображение.
Хорошей новостью является то, что я могу взломать AngularJS, чтобы заставить мою систему работать, но плохая новость заключается в том, что мне не нравится это делать. Я бы предпочел остаться с Angular для всей моей клиентской серверной связи.
Я собираюсь открыть отдельную проблему в Stack Overflow, которая касается только вопросов GET byte [], которые у меня есть с AngularJS. Если я смогу получить разрешение, я обновлю эту проблему с помощью решения в исторических целях, чтобы помочь другим.
Обновление
Эрик Эслингер из Группы Google отправил мне небольшой сегмент кода, в котором подчеркивается, что responseType должен быть "arraybuffer", все в нижнем регистре. Я обновил блок кода выше, чтобы показать строчное значение и добавил примечание.
Спасибо...