windows-file-copy-300x127

Upload Files from Windows Phone

Posted on August 19, 2011 by

When speaking to a crowd of Windows Phone developers the other day, I was asked an interesting question about uploading files. We talk about how, with Mango, you can use the BackgroundAgents to download tons of data to the device, but we never talk about uploading. As I understand it (at least as of this writing) although uploads are limited to 5MB, there are no good samples out there on *how* to upload them. Sure, I can use the built-in Facebook or Skydrive sharing features, but where's the fun in that? What if I want to be able to post to my *own* repository? This post is my attempt to answer that question – it’s as much for me to remember how I did it as it will hopefully be helpful to you to see how I accomplished it.

To make it more interesting, I decided that I would implement the server as an MVC application, and only accept REST-based POST actions through a FileController (that’s for you, Amir).

So, here’s the code – I hope you enjoy it!

Here’s my Controller (FileController.cs)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class FileController : Controller
    {
        [HttpPost]
        public ActionResult Upload()
        {
            string filename = Server.MapPath("/Uploads/" + Path.GetRandomFileName();
            try
            {
                using (FileStream fs = new FileStream(filename), FileMode.Create))
                {
                    using (BinaryWriter bw = new BinaryWriter(fs))
                    {
                        using (BinaryReader br = new BinaryReader(Request.InputStream))
                        {
                            long bCount = 0;
                            long fileSize = br.BaseStream.Length;
                            const int BLOCK_SIZE = 4096;
                            byte[] bytes = new byte[BLOCK_SIZE];
                            do
                            {
                                bytes = br.ReadBytes(BLOCK_SIZE);
                                bCount += bytes.Length;
                                bw.Write(bytes);
                            } while (bCount < fileSize);
                        }
                    }
                }

                return Json(new { Result = "Complete" });
            }
            catch (Exception ex)
            {
                return Json(new { Result = "Error", Message = ex.Message });
            }
        }
    }
}

And here's my MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;

namespace PhoneApp10
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        private void SelectButton_Click(object sender, RoutedEventArgs e)
        {
            PhotoChooserTask task = new PhotoChooserTask();
            task.Completed += task_Completed;
            task.Show();
        }

        private void task_Completed(object sender, PhotoResult e)
        {
            if (e.TaskResult != TaskResult.OK)
                return;

            const int BLOCK_SIZE = 4096;

            Uri uri = new Uri("http://localhost:4223/File/Upload", UriKind.Absolute);

            WebClient wc = new WebClient();
            wc.AllowReadStreamBuffering = true;
            wc.AllowWriteStreamBuffering = true;

            // what to do when write stream is open
            wc.OpenWriteCompleted += (s, args) =>
            {
                using (BinaryReader br = new BinaryReader(e.ChosenPhoto))
                {
                    using (BinaryWriter bw = new BinaryWriter(args.Result))
                    {
                        long bCount = 0;
                        long fileSize = e.ChosenPhoto.Length;
                        byte[] bytes = new byte[BLOCK_SIZE];
                        do
                        {
                            bytes = br.ReadBytes(BLOCK_SIZE);
                            bCount += bytes.Length;
                            bw.Write(bytes);
                        } while (bCount < fileSize);
                    }
                }
            };

            // what to do when writing is complete
            wc.WriteStreamClosed += (s, args) =>
            {
                MessageBox.Show("Send Complete");
            };

            // Write to the WebClient
            wc.OpenWriteAsync(uri, "POST");
        }
    }
}

I wrote this using the latest tools available at the time - which is the Windows Phone SDK 7.1 Beta 2 Refresh, so YMMV depending on which version of the tools you're using. I am hopeful that one day I'll be able to look back at this post and laugh at how much code it took to do this simple file upload...

Comments (14)

 

  1. Suman says:

    after we have uploaded the image how can we get data from the server or a website?

  2. Tomi Rinne says:

    I’m trying to do this via VB.Net-code. Could you help me, please? :)

  3. Ayush Saraswat says:

    I’m trying to upload an audio file to a php script. How can I do this?

  4. hi,
    how should i add using System.Web.Mvc in FileController.cs.? IS there any apeciall dll to be added.?

  5. Juan Diego says:

    Hi Chris,
    bw.Write(bytes) keeps increasing memory usage, even when setting AllowWriteStreamBuffering=false. So still limited to some file sizes depending on available memory. Ie, you cannot upload a 5mb file if available memory for the app is 5mb or less. It gets even worse when you try to upload from inside a Scheduled Task where memory cap is 5mb…
    I have also tried with HttpWebRequest, its so frustrating…

  6. Gina says:

    Excuse me

    I am s student , and start learning window phone

    Could you share your file to me?

    Because I cannot find my file which I uploaded.

  7. subbu says:

    Nice its work well for HTTP server,but when i try to connect my ftp server, i shows an exception like “server is not found”..And my requirement is to upload an image file to my ftp server from windows phone media library..please get back to my problem.

    Thanks in advance,
    subbu

  8. subbu says:

    Thanks for reply,But i had already tried that source code from http://silverlightftp.codeplex.com/ ..And its not work well for windows phone and i am not getting better answer

    • Chris Koenig says:

      Yeah, if there aren’t any open source solutions, you’ll need to write your own class to negotiate the FTP conversation. I bet if you search around you’ll find some FTP solutions that will work on Windows Phone. You’ll probably need to make some minor tweaks to them, and recompile them from Silverlight or .NET, but I’m sure they’re out there…

      Sorry I couldn’t be more help!

  9. Arvind says:

    how to get response from server after uploading image?

  10. sonali says:

    how to read the response from the server after uploading the file?

  11. Joseph Davis says:

    Hi Chris,
    I read your tutorial above and used it to upload an image to a server and the upload works perfectly.But when i add an image to my code to act as a preview using the below code

    BitmapImage bmp = new BitmapImage();
    bmp.SetSource(e.ChosenPhoto);

    UploadedImage.Source = bmp;

    the upload does not work anymore.Please any help

  12. Swanand Kulkarni says:

    I want to upload photo image using fileupload control and want to save in applications local folder.

    I googled too much however not getting any senario like this.

    if it is possible then do help.

    thank you.