2013-06-03 2 views
6

Я пытаюсь загрузить файлы из локального клиента командной строки в Azure storage через web-api. Я использую для этого веб-сайт Azure. Работа с клиентом не является проблемой. И у меня все работает нормально. Вот код веб-апи:Загружайте файлы в хранилище Azure Blob через WebApi без доступа к локальной файловой системе

public async Task<HttpResponseMessage> PostUpload() 
    { 
     // need a local resource to store uploaded files temporarily 
     LocalResource localResource = null; 
     try 
     { 
      // Azure web-site fails here 
      localResource = RoleEnvironment.GetLocalResource("TempStorage"); 
     } 
     catch (Exception e) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Unable to get access to local resources"); 
     } 

     var provider = new MultipartFormDataStreamProvider(localResource.RootPath); 

     // Read the form data. 
     await Request.Content.ReadAsMultipartAsync(provider); 

     // snipped validation code 
     var container = // code to get container 

     foreach (var fileData in provider.FileData) 
     { 
      var filename = GetBlobName(fileData); 
      var blob = container.GetBlockBlobReference(filename); 
      using (var filestream = File.OpenRead(fileData.LocalFileName)) 
      { 
       blob.UploadFromStream(filestream); 
      } 
      File.Delete(fileData.LocalFileName); 
     } 

     return Request.CreateResponse(HttpStatusCode.OK); 
    } 

Все отлично работает, когда я бегу на месте, но, как только я раскрываю веб-сайт в лазури, я не могу загрузить, потому что Azure Web-сайты не имеют доступ к LocalResource. И мне нужно переключиться на Azure Web-Role. Я могу переключиться, но доступ к локальной файловой системе беспокоит меня все вместе.

И LocalResource требуется, например, для MultipartFormDataStreamProvider(). И я не нашел альтернативных способов загрузки файлов в WebApi. Мой план состоял в channel through upload directly to Azure, не сохраняя ничего на локальном жестком диске.

Есть ли способ загрузить файлы?

p.s. Я видел usages of Shared Access Signatures, где я могу предоставить клиентскому приложению URL-адрес с подписью и позволить клиенту загружать непосредственно в Azure Blog. Но я не уверен, насколько это безопасно и не очень удобно (пока) с передачей подписей к клиенту. В настоящий момент я предполагаю, что клиент будет запущен в очень агрессивной среде, и ничто не может быть доверено возвращаться от клиента.

UPD Мое окончательное решение связано с использованием только единой сигнатуры доступа, выданной на сервере и передаваемой клиенту. Затем клиент загружает файлы непосредственно в Azure. Таким образом, я сохраняю много хлопот с управлением загруженными файлами. И вот more detailed description моего решения.

+0

Какое исключение выбрасывает следующий код "localResource = RoleEnvironment.GetLocalResource (" TempStorage ")" –

+0

Вы удобно используете REST API? –

+0

@BrianDishaw Исключение составляет нечто вроде строк «Невозможно получить LocalResource, System.Runtime.InteropServices.SEHException (0x80004005): внешний компонент выбрал исключение ». Также эта страница (http://msdn.microsoft.com/en-us/library/windowsazure/ee758708.aspx) предполагает, что локальные ресурсы предназначены только для веб- и Рабочие роли, а не веб-сайты. – trailmax

ответ

11

Это не совсем тот ответ, который вы ищете, но вы можете использовать локальное хранилище с веб-сайтами Azure, используя MultiPartFileStreamProvider и Path.GetTempPath(). Код будет выглядеть примерно так, как этот

public async Task<HttpResponseMessage> PostUpload() 
{ 
    var provider = new MultipartFileStreamProvider(Path.GetTempPath()); 

    // Read the form data. 
    await Request.Content.ReadAsMultipartAsync(provider); 

    // do the rest the same  
} 
+0

Теперь мне интересно, как Azure управляет TempPath() на веб-сайтах и ​​насколько он надежный. Не удалось ли его стереть на полпути через загрузку большого файла? – trailmax

+0

мертвая ссылка, Даниэль. – Bon

+0

Я удалил мертвую ссылку, указывающую, что временная директория не является временной. Насколько мне известно, это все еще так. –

1

Одно из возможных решений, чтобы получить код для работы как с LocalResource бы провести эту внутреннюю часть рабочего процесса, что само-хосты Web API через Owin.

Вы можете найти простое пошаговое руководство по адресу: http://www.asp.net/web-api/overview/hosting-aspnet-web-api/host-aspnet-web-api-in-an-azure-worker-role

Вам просто нужно для запуска в Owin размещаемый API в рамках метода OnStart() из RoleEntryPoint. Имейте в виду, что вы также можете вернуть Html из ответа веб-api, чтобы вы могли сделать роль рабочего очень гибким базовым проектом.

Вот краткий фрагмент, показывающий, как настроить хост Owin по ссылке выше:

+0

Я мог бы просто развернуть сайт в веб-роли и получить доступ к LocalResource. Развертывание только web-api в роли рабочего является излишним. Во всяком случае, я решил проблему, выпустив подпись общего доступа для записи в хранилище blob, передав ее клиенту через WebApi. А затем клиент загружает файлы непосредственно в Azure. – trailmax

2

Я нашел эту статью StackOverflow, который переопределяет MultipartFormDataStreamProvider так, что файлы не хранятся локально первый, но непосредственно записывается AWSStream. См.: Is it possible to override MultipartFormDataStreamProvider so that is doesn't save uploads to the file system?

Но я должен сказать, что мне также нравится решение trailmax.

Смежные вопросы