Monday, November 8, 2010

Uploading Files to Google App Engine

In previous post we talked about sending emails with attachments from the Google App Engine.
But how do we get files from a client to the cloud?

Here is a sample code in C#:

public static string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection nvc, string cookie)
{
    string boundary = "----------------------------" +
    DateTime.Now.Ticks.ToString("x");

    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
    httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
    httpWebRequest.Method = "POST";
    httpWebRequest.KeepAlive = true;
    httpWebRequest.Headers["Cookie"] = cookie;
    httpWebRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;

    Stream memStream = new MemoryStream();

    byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

    string formdataTemplate = "\r\n--" + boundary +
        "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

    foreach (string key in nvc.Keys)
    {
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        memStream.Write(formitembytes, 0, formitembytes.Length);
    }

    memStream.Write(boundarybytes, 0, boundarybytes.Length);
    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\n\r\n";

    for (int i = 0; i < files.Length; i++)
    {
        string header = string.Format(headerTemplate, "file" + i, files[i]);
        byte[] headerbytes = Encoding.UTF8.GetBytes(header);

        memStream.Write(headerbytes, 0, headerbytes.Length);

        FileStream fileStream = new FileStream(files[i],
            FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[1024];

        int bytesRead = 0;

        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
        {
            memStream.Write(buffer, 0, bytesRead);

        }
        memStream.Write(boundarybytes, 0, boundarybytes.Length);
        fileStream.Close();
    }

    httpWebRequest.ContentLength = memStream.Length;

    Stream requestStream = httpWebRequest.GetRequestStream();

    memStream.Position = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    memStream.Read(tempBuffer, 0, tempBuffer.Length);
    memStream.Close();
    requestStream.Write(tempBuffer, 0, tempBuffer.Length);
    requestStream.Close();

    WebResponse webResponse = httpWebRequest.GetResponse();

    Stream stream = webResponse.GetResponseStream();
    StreamReader reader = new StreamReader(stream);

    string responseFromServer = reader.ReadToEnd();

    webResponse.Close();
    reader.Close();
    stream.Close();
    httpWebRequest = null;
    webResponse = null;

    return responseFromServer;
}

The method above has a cookie as a parameter. Here is an excellent site by Dale Lane where you can see how to access authenticated Google App Engine service from a C# client.

No comments:

Post a Comment