Silverlight jest technologią odpowiedzialną za tworzenie warstwy prezentacji po stronie klienta. Wszelki kod wykonywany jest w przeglądarce zatem nie ma bezpośredniego dostępu do serwera www. Czasami jednak aplikacja musi wysyłać do serwera jakieś pliki np. graficzne (w przypadku modułu galerii zdjęć). Niestety ze względu na opisaną lokalność działania, Silverlight nie wspiera tego. Jedną z metod obejścia jest implementacja własnego HTTP handlera. Zacznijmy więc od stworzenia aplikacji Silverlight hostowanej za pomocą ASP .NET. Następnie dodajemy HTTP handler ( Add –> New Item –> Web –>Generic Handler), który będzie odpowiedzialny za zapis pliku na dysku. Silverlight będzie wysyłał żądania zapisu pliku na serwerze właśnie do tego handlera. Kod handler’a nie jest zbyt skomplikowany:
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class FileReceiver : IHttpHandler { public void ProcessRequest(HttpContext context) { string filename = context.Request.QueryString["filename"].ToString(); string destFileName = "docelowa sciezka"; using (FileStream fs = File.Create(destFileName)) { SaveFile(context.Request.InputStream, fs, destFileName); } } private void SaveFile(Stream stream, FileStream fs) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0) { fs.Write(buffer, 0, bytesRead); } fs.Close(); } public bool IsReusable { get { return false; } } }
Jak widać handler po prostu odczytuje nazwę pliku zapisanego w parametrze filename (QueryString) a następnie zapisuje otrzymane dane na dysku. Jeśli użyliśmy szablonu Generic Handler już nic więcej po stronie serwera nie musimy dodawać ani konfigurować. Przejdźmy teraz do aplikacji klienckiej (Silverlight’a). W celu wysłania pliku będziemy wykorzystywać klasę WebClient:
Stream data = fileInfo.OpenRead(); string address="http://localhosty:1354/FileReceiver.ashx?filename=nazwa_pliku"; WebClient c = new WebClient(); c.OpenWriteCompleted += (sender, e) => { PushData(data, e.Result); e.Result.Close(); data.Close(); }; c.OpenWriteAsync(address);
gdzie PushData to:
private void PushData(Stream input, Stream output) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0) { output.Write(buffer, 0, bytesRead); } }
Oczywiście na koniec należy dodać jeszcze jakiś TextBox oraz Button, który będzie wywoływał OpenFileDialog (wybieranie pliku).
Świetna sprawa! Jak dla mnie bomba. Nawet nie wiedziałem iż ashx potrafi takie rzeczy:)
Tak patrzę na ten przykład i czy nie ma błędu w kodzie pliku FileReceiver.ashx? Bo metoda SaveFile przyjmuje dwa parametry, a widzę że przekazujesz do niej trzy.
Abstrahując od treści sugerowałbym ustawienie szerokości strony na większą.