Silverlight: Upload and Display Image
August 29, 2009 2 Comments
I’m working on a little pet Silverlight project and thought I’d share a quick solution. I wanted to see if I could upload and image to the server, then turn around and download that image and display it. This works in Silverlight 3.
The XAML:
<UserControl x:Class="ImageEditor.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" MouseMove="UserControl_MouseMove">
<Grid x:Name="LayoutRoot" Background="Azure" Width="800" Height="600">
<Image x:Name="MainImage" Source="images/image.jpg" Width="300" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
<Button x:Name="UploadImage" Click="UploadImage_Click" Content="Upload"></Button>
</Grid>
</UserControl>
The Code:
private void UploadImage_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Multiselect = false;
dlg.Filter = "All files (*.*)|*.*|PNG Images (*.png)|*.png";
bool? retval = dlg.ShowDialog();
if (retval != null && retval == true)
{
UploadFile(dlg.File.Name, dlg.File.OpenRead());
StatusText.Text = dlg.File.Name;
}
else
{
StatusText.Text = "No file selected...";
}
}
private void UploadFile(string fileName, Stream data)
{
string host = Application.Current.Host.Source.AbsoluteUri;
host = host.Remove(host.IndexOf("/ClientBin"));
UriBuilder ub = new UriBuilder(host + "/receiver.ashx");
ub.Query = string.Format("filename={0}", fileName);
WebClient c = new WebClient();
c.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
c.WriteStreamClosed += (sender, e) =>
{
LoadImage(fileName);
};
c.OpenWriteAsync(ub.Uri);
}
private void LoadImage(string fileName)
{
//
// Creating WebClient object and setting up events
//
WebClient downloader = new WebClient();
downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted);
//downloader.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downloader_DownloadProgressChanged);
//
// Specify Image to load
//
string host = Application.Current.Host.Source.AbsoluteUri;
host = host.Remove(host.IndexOf("/ClientBin"));
fileName = host + "/images/" + fileName;
downloader.OpenReadAsync(new Uri(fileName, UriKind.Absolute));
}
void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
//
// Create a new BitmapImage and load the stream
//
BitmapImage loadedImage = new BitmapImage();
loadedImage.SetSource(e.Result);
//
// Setting our BitmapImage as the source of a imageControl control I have in XAML
//
MainImage.Source = loadedImage;
}
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);
}
}
The Handler (receiver.ashx):
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class receiver : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string filename = context.Request.QueryString["filename"].ToString();
using (FileStream fs = File.Create(context.Server.MapPath("~/images/" + filename)))
{
SaveFile(context.Request.InputStream, fs);
}
}
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);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
Credit is due to Nipun Tomar for the file uploading stuff and Kirupa.com for the help with loading images on demand. You can get the details on how this code works from those two links. Enjoy!