Как загрузить файлы в RackSpace Cloud Files с помощью .net?

Я хочу использовать CDN RackSpace (облачные файлы) для хранения своего статического контента. Проблема в том, что я использую ASP.NET MVC3, и я не видел ни одного текущего рабочего примера того, как это сделать.

Я видел несколько примеров в Интернете, но все они были версии, которую RackSpace больше не поддерживает. Вы можете подтвердить это здесь, в их Примечании:

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

И когда вы проверяете учетную запись gitHub RackSpace под openstack.net, на который перенаправляется их поддержка, вы видите, что нет поддержки загрузки файлов в Cloud Files. Вы можете увидеть это в таблице файлов:

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

Как программно загрузить файлы в облачные файлы RackSpace с помощью C#?


person eestein    schedule 29.03.2013    source источник


Ответы (2)


Вы правы, на данный момент проект openstack.net не поддерживает CloudFiles. Эта функция должна быть выпущена в конце этого месяца (середина апреля). Вы по-прежнему можете использовать csharp-cloudfiles (https://github.com/rackerlabs/csharp-cloudfiles), если хотите, поскольку он все еще работает, он просто устарел и не будет получать никаких обновлений или исправлений ошибок.

Тем не менее, вот быстрое и грязное консольное приложение, использующее встроенные объекты HttpWebRequest/Response, которое должно помочь вам начать работу до тех пор, пока не будет выпущена версия openstack.net v1.1.

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);
        }
    }
}

В приведенном выше коде я предоставил как асинхронный, так и синхронный метод, поэтому вам не нужны оба, просто используйте тот, который лучше всего подходит для вас.

вы также можете использовать библиотеку HttpClient, если у вас установлен пакет NuGet Http Client (http://nuget.org/packages/Microsoft.Net.Http/2.0.20710.0). Вот пример:

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);
}

Надеюсь, это поможет!

person alanquillin    schedule 04.04.2013
comment
Спасибо Алан, это уже было решено. Вы тот, кто ответил на мой билет. Спасибо. - person eestein; 15.04.2013
comment
@alanquillin Я полагаю, что на данный момент опубликована версия 1.1, и указанная выше библиотека больше не рекомендуется? Есть ли где-нибудь обновленный пример для использования с OpenStack.net? - person Marc M; 28.06.2013

По состоянию на 2014 год и ответ Марку М., вот как это должно быть сделано:

Сначала установите пакет openstack.net

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

PM> Install-Package openstack.net

Код для загрузки:

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);
}

Использование:

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

Просто обратите внимание, что некоторые части являются моими техническими требованиями, такими как создание слага, использование Guid, Region и т. д.

person eestein    schedule 23.12.2014