НА ЗАМЕТКУ
При использовании Web-служб справедлив тезис, в соответствии с которым лучше передавать двоичные данные в результате выполнения второго запроса, чем пытаться сразу же передавать большой поток XML-данных. Поскольку объем двоичных данных при преобразовании их к формату XML значительно возрастает, это приводит к увеличению длительности их передачи. При длительных временах передачи возрастает вероятность сбоев. Улучшенная модель предполагает выполнение одного вызова Web-службы для передачи всех данных, которые могут быть эффективно переданы в виде XML, и ряда последующих вызовов для передачи таких двоичных файлов, как файлы изображений. В листинге 15.11 представлен код, позволяющий загрузить файл с Web-сервера и сохранить его на устройстве. Если необходимо передать содержимое нескольких двоичных файлов, имеет смысл поэкспериментировать с объединением всех двоичных данных в один сжатый файл; такой объединенный файл может быть передан в виде двоичных данных и распакован на другом конце канала связи.
В листинге 15.9 приведен пример неэффективной организации работы с Web-службой с использованием многократных запросов и ответов. В листинге 15.10 представлен пример пакетной организации того же диалога, когда вся необходимая обработка осуществляется при помощи одного цикла "запрос/ответ". При любом удобном случае старайтесь уменьшать количество запросов, объединяя несколько мелких запросов в один более емкий.
Листинг 15.9. Неэффективная организация диалога с Web-службой, в которой используется множество вызовов
//--------------------------
//Создать и обработать заказ
//--------------------------
//0. Установить связь
int sessionID = someWebService.LogOn(userCredentials);
//1. Вызвать Web-службу и создать новый заказ
int orderID = someWebService.CreateNewOrder(sessionID, userInfo, productInfo);
//2. Вызвать Web-службу и передать информацию о платеже
someWebService.ConfirmPayment(sessionID, orderID, paymentInfo);
//3. Вызвать Web-службу и передать информацию о доставке
someWebService.ConfirmShipping(sessionID, orderID, shippingAddress);
//4. Вызвать Web-службу и завершить оформление заказа
someWebService.FinalizeOrder(sessionID, orderID);
Листинг 15.10. Группирование запросов в одном вызове Web-службы
//----------------------------------------------------------
//Создать и обработать заказ посредством группового запроса,
//включающего:
// 0. Начало связи
// 1. Создание нового заказа
// 2. Подтверждение платежа
// 3. Подтверждение доставки
// 4. Завершение оформления заказа
//-----------------------------------------------------------
//Сделать все за один раз
someWebService.BatchCreateOrder(userCredentials, userInfo, paymentInfo, shippingAddress);
В листинге 15.11 показан пример кода, который загружает с сервера двоичный файл и сохраняет его локально на устройстве. Этот код может пригодиться вам при загрузке с сервера файлов, подобных файлам изображений.
Листинг 15.11. Код для загрузки файла с Web-сервера
//-----------------------------------------------------------
//Осуществляет синхронную загрузку файла с Web-сервера
//и сохраняет его в локальной файловой системе
// [in] httpWhereFrom: URL-адрес файла
// (например, "http://someserver/somefile.jpg")
// [in] filenameWhereTo: Место, куда необходимо записать файл
// (например, "\\localfile.jpg")
//-----------------------------------------------------------
public void downloadFileToLocalStore(string httpWhereFrom, string filenameWhereTo) {
System.IO.FileStream myFileStream = null;
System.IO.Stream myHTTPResponseStream = null;
System.Net.WebRequest myWebRequest = null;
System.Net.WebResponse myWebResponse = null;
//Если файл, который мы хотим записать, уже существует, удалить его
if (System.IO.File.Exists(filenameWhereTo) == true) {
System.IO.File.Delete(filenameWhereTo);
}
try {
//Создать Web-запрос
myWebRequest = System.Net.HttpWebRequest.Create(httpWhereFrom);
//Получить ответ
myWebResponse = myWebRequest.GetResponse();
//Получить поток для ответа
myHTTPResponseStream = myWebResponse.GetResponseStream();
//Создать локальный файл, в который необходимо направить поток ответа
myFileStream = System.IO.File.OpenWrite(filenameWhereTo);
//Этот размер буфера является настраиваемым
const int buffer_length = 4000;
byte [] byteBuffer = new byte[buffer_length];
int bytesIn;
//Считать файл и направить поток данных в локальный файл
do {
//Считать данные
bytesIn = myHTTPResponseStream.Read(byteBuffer, 0, buffer_length);
//Записать данные
if (bytesIn != 0) {
myFileStream.Write(byteBuffer, 0, bytesIn);
Читать дальше