Question

I want to use RackSpace's CDN (Cloud Files) to store my static content. The problem is I am using ASP.NET MVC3 and I have not seen any current working example of how to do that.

I saw several examples online but they were all of a version RackSpace is not supporting anymore. You can confirm that here on their Note:

http://www.rackspace.com/knowledge_center/article/sample-csharp-application-for-cloud-files

And when you check RackSpace's gitHub account under openstack.net, which is the project their support redirects to, you see that there's no support for uploading files to Cloud Files. You can see that under Files table:

https://github.com/rackspace/openstack.net/wiki/Feature-Support

How can I upload files to RackSpace's Cloud Files programmatically using C#?

Was it helpful?

Solution

You are correct, at the moment the openstack.net project does not support CloudFiles. That functionality is slated to be released later this month (Mid April). You can still use the csharp-cloudfiles (https://github.com/rackerlabs/csharp-cloudfiles) if you would like, as it still works, it is just in a deprecated state and will not be receiving any updates or bug fixes.

However, here is a quick and dirty console app, using the built in HttpWebRequest/Response objects, that should help you get started until the openstack.net v1.1 is released.

class Program
{
    const string filePath = @"Path\FileName";
    const string myToken = "myToken";
    const string url = "Url/Container/FileName";

    static void Main(string[] args)
    {
        //Do();
        DoAsync();
    }

    static void Do()
    {
        using (var fs = File.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            UploadStream(new Uri(url), fs, myToken,
                (response) => Console.WriteLine("Upload Complete.  Status Code: {0} ({1})", response.StatusCode, response.StatusDescription));
        }

        Console.WriteLine("Done!");
        Console.ReadLine();
    }

    static void DoAsync()
    {
        IAsyncResult asyncRes;
        using (var fs = File.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            asyncRes = UploadStreamAsync(new Uri(url), fs, myToken,
                (asyncResult) =>
                {
                    var request = (HttpWebRequest)asyncResult.AsyncState;
                    var response = (HttpWebResponse)request.EndGetResponse(asyncResult);
                    Console.WriteLine("Upload Complete.  Status Code: {0} ({1})", response.StatusCode, response.StatusDescription);
                });
        }

        asyncRes.AsyncWaitHandle.WaitOne();

        Console.WriteLine("Done!");
        Console.ReadLine();
    }

    static IAsyncResult UploadStreamAsync(Uri uri, Stream contents, string token, AsyncCallback resultCallback, int chunkSize = 8 * 1024)
    {
        var req = (HttpWebRequest)WebRequest.Create(uri);
        req.Headers.Add("X-Auth-Token", token);
        req.Method = "PUT";

        req.AllowWriteStreamBuffering = false;
        if (req.ContentLength == -1L)
            req.SendChunked = true;

        using (Stream stream = req.GetRequestStream())
        {
            var buffer = new byte[chunkSize];
            int count;
            while ((count = contents.Read(buffer, 0, chunkSize)) > 0)
            {
                stream.Write(buffer, 0, count);
            }
        }

        return req.BeginGetResponse(resultCallback, req);
    }

    static void UploadStream(Uri uri, Stream contents, string token, Action<HttpWebResponse> resultCallback, int chunkSize = 8 * 1024)
    {
        var req = (HttpWebRequest)WebRequest.Create(uri);
        req.Headers.Add("X-Auth-Token", token);
        req.Method = "PUT";

        req.AllowWriteStreamBuffering = false;
        if (req.ContentLength == -1L)
            req.SendChunked = true;

        using (Stream stream = req.GetRequestStream())
        {
            var buffer = new byte[chunkSize];
            int count;
            while ((count = contents.Read(buffer, 0, chunkSize)) > 0)
            {
                stream.Write(buffer, 0, count);
            }
        }

        using (var resp = req.GetResponse() as HttpWebResponse)
        {
            resultCallback(resp);
        }
    }
}

In the code above, I have provided both and Async and a Synchronous method, so you do not need both, just use that one that works best for you.

you can also use the HttpClient library if you have the Http Client NuGet package installed (http://nuget.org/packages/Microsoft.Net.Http/2.0.20710.0). Here is a sample:

static void UploadFileToRSCloud(string path, string filename)
{
    HttpClient client = new HttpClient();
    MemoryStream ms = new MemoryStream();

    client.DefaultRequestHeaders.TransferEncodingChunked = true;

    var filePath = 
    // Copy the data to the Resource Part 
    using (FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        CopyStream(fileStream, ms);
    }// end:using(fileStream) - Close and dispose fileStream. 

    ms.Position = 0;
    StreamContent sc = new StreamContent(ms);

    client.DefaultRequestHeaders.Add("X-Auth-Token", "TOKEN HERE");

    var result = client.PutAsync( "UrlBase/Container/ChipperJones.jpg", sc);

    result.Wait();
}

private static void CopyStream(Stream source, Stream target)
{
    const int bufSize = 0x1000;
    byte[] buf = new byte[bufSize];
    int bytesRead = 0;
    while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
        target.Write(buf, 0, bytesRead);
}

Hope that helps!

OTHER TIPS

As of 2014 and replying to Marc M, this is how it should be done:

First install the openstack.net package

https://www.nuget.org/packages/openstack.net/

PM> Install-Package openstack.net

The code to upload:

public static string Upload(Stream stream, string fileName)
{
    CloudFilesProvider cloudFilesProvider = getProvider();
    IEnumerable<string> containerObjectList = 
        cloudFilesProvider.ListObjects(CONTAINER_NAME, region: REGION_DFW)
        .Select(o => o.Name);
    string extension = Path.GetExtension(fileName);
    string name = Path.GetFileNameWithoutExtension(fileName);

    stream.Position = 0;

    name = name.GenerateSlug(); //my method
    fileName = name + extension;

    while (containerObjectList.Contains(fileName))
        fileName = name + Guid.NewGuid().ToString().Split('-')[0] + extension;

    cloudFilesProvider
        .CreateObject(CONTAINER_NAME, stream, fileName, region: REGION_DFW);

    return Constants.Rackspace.CloudFiles.PUBLIC_CONTAINER + fileName;
}

private static CloudFilesProvider getProvider()
{
    CloudIdentity cloudIdentity = 
        new CloudIdentity() { APIKey = API_KEY, Username = USERNAME };
    return new CloudFilesProvider(cloudIdentity);
}

Usings:

using net.openstack.Core.Domain;
using net.openstack.Providers.Rackspace;

Just take note that some parts are my technical requirements like generating a slug, using Guid, Region, etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top