Форум программистов, компьютерный форум, киберфорум
Наши страницы
Mans7
Войти
Регистрация
Восстановить пароль
Оценить эту запись

[Silverlight] W-1. Загрузка файла с сервера

Запись от Mans7 размещена 03.02.2013 в 14:57
Обновил(-а) Mans7 03.02.2013 в 16:42

В рамках моего проекта мне понадобилось иметь возможность распечатывать некоторые документы прямо из приложения. То есть, скажем, некий договор. Приложение Silverlight оперируя данными из базы данных должно скачать из некоего источника (сервера) шаблон договора (если его нету на локальной машине), подредактировать его и вывести на печать.

Пишу здесь не столько для других - сколько для себя - т.к. тема весьма важная и востребованная. Эта тема будет разбита на 3 записи в блоге.

Содержание:
1. W-1. Загрузка файла с сервера. (в частности *.doc файла)
2. W-2. Редактирование документа word в фоне.
3. W-3. Вывод документа на печать.

Приступим к первой фазе этой цепочки: W-1. Загрузка файла с сервера.

Задача стоит весьма простая - получить документ с сервера (шаблон договора) на жесткий диск, либо в оперативную память компьютера. Так как я не представляю как можно было бы редактировать word документ, который ниже в коде будет представлять собой массив байтов, то его необходимо записать в некий файл (моих знаний пока что для такого трюка недостаточно). Технология Silverlight имеет ряд ограничений в области доступа к файловой системе. Мы имеем прямой доступ к изолированному хранилищу. Технически с помощью COM можно несколько расширить доступ (как минимум, в папку общих документов (а-ля Мои документы)), но я не вникал в это. Например, что бы открыть диалоговое окно (сохранить/открыть файл), код вызова диалогового окна должно находиться открыто в методе события, которое вызывает непосредственно пользователь, а именно - Click, MouseLeftButtonUp и пр. Это обязательное условие в соответствии с политикой безопасности Microsoft. Даже если написать код вызова диалогового окна в нужном методе, но внутри блока try-catсh - будет так же получено исключение безопасности.

Как выяснилось, полученная задача решилась достаточно просто, хоть и не очень очевидно. В десятках попыток получить файл с сервера приложением silverlight, постоянно возникало исключение доступа. Позже стало ясно, что проблема не в коде, а в сервере. А точнее его политике доступа. Для решения данной проблемы я создал и поместил в корневой каталог сервера (сайта) следующие 2 файла:

- crossdomain.xml
XML
1
2
3
s<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
-clientaccesspolicy.xml
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<access-policy>
    <cross-domain-access>
        <policy>
            <allow-from http-request-headers="*">
                <domain uri="*"/>
            </allow-from>
            <grant-to>
                <resource path="/" include-subpaths="true"/>
            </grant-to>
        </policy>
    </cross-domain-access>
</access-policy>
После чего исключение доступа перестало напоминать о себе. Позже я изменю эти файлы что бы не было доступа "ото всех ко всем".

Примечание: подробнее почитать о назначении этих файлов можно здесь http://msdn.microsoft.com/en-us/library/cc197955(VS.95).aspx, пример применения - http://www.silverlighthack.com/post/...t-1-of-2).aspx

А дальше всё просто - пишем процедуру чтения и записи файла. Начнем с чтения:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void Test1btn_Click_1(object sender, RoutedEventArgs e)
        {
            byte[] bytes;
            WebClient webClient = new WebClient();
            webClient.OpenReadCompleted += (s, e2) =>
            {
                Stream stream = e2.Result;
                MemoryStream ms = new MemoryStream();
                stream.CopyTo(ms);
                bytes = ms.ToArray();
 
                try
                {
                    //ЗДЕСЬ ПИСАТЬ ПРОЦЕДУРУ ЗАПИСИ В ФАЙЛ 
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                
            };
            webClient.OpenReadAsync(new Uri("http://www.nachos.com/CIA_passwords.doc"), UriKind.Absolute);
        }
Кстати, чтобы показать диалоговое окно для того что бы пользователь сам указал под каким именем и где сохранить файл, следует написать в самом начале следующее:
C#
1
2
3
            SaveFileDialog dialog = new SaveFileDialog();          
            bool? dialogResult = dialog.ShowDialog();
            if (dialogResult != true) return;
Далее пишем полученный массив байтов в файл. Для записи в файл, который был выбран пользователем надо использовать следующий кусок кода:
C#
1
2
3
4
5
6
7
                    //Get the file stream
                    using (Stream fs = (Stream)dialog.OpenFile())
                    {
                        fs.Write(bytes, 0, bytes.Length);
                        fs.Close();
                       //File successfully saved
                    }
А для записи файла в изолированное хранилище (ВНИМАНИЕ! при использовании изолированного хранилища, учитывайте его стандартную квоту, и, если надо, заранее расширяйте её, однако это повлечёт запрос согласия пользователя на увеличения квоты) я использовал такой код:
C#
1
2
3
4
5
6
7
8
9
                    using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        using (IsolatedStorageFileStream isfs = isf.CreateFile("test1.doc"))
                        {
                            BinaryWriter bw = new BinaryWriter(isfs);
                            bw.Write(bytes);
                            bw.Close();
                        }
                    }
На заметку: при использовании не BinaryWriter, а StreamWriter и записи в файл через Write(bytes), был получен doc файл с текстом System.Byte [].


Вот, пожалуй и всё с первой частью. Проверить наличие файла в изолированном хранилище можно по адресу (для Windows 7) - %userprofile%\AppData\LocalLow\Microsoft\Silverlight\is

Так же, можно было бы сделать zip архив на сервере для хранения шаблонов документов, который приложение бы само распаковывало после загрузки на компьютер (/в память). Это экономит время на загрузку документов, но, когда оные очень малы (и их количество так же малО), я считаю такой подход в конкретно этой ситуации не принципиальным. Для крупных файлов имеет смысл отслеживание процесса загрузки данных. Но это совершенно другая тема...

Для решения задачи мне помогли следующие источники:
1. sql.ru - http://www.sql.ru/forum/actualthread.aspx?tid=806235
2. stackoverflow.com - http://stackoverflow.com/questions/2...om-silverlight
3. social.msdn.microsoft.com - http://social.msdn.microsoft.com/For...4-6681f9597b61
3. гугл

_____________________________
Я не считаю вышеуказанные решения идеальными, но они работают. Сделано это с целью ознакомления и получения первичного опыта в области чтения-записи данных с сервера используя технологию Silverlight. Если вы можете подсказать более грамотное решение - буду рад почитать его в комментариях.
Размещено в Без категории
Просмотров 1237 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru