2013-07-02 3 views
0

Azure Blob 저장소에 미디어를 완벽하게 저장하는 새로운 MediaFileSystemProvider를 만들려고합니다.Umbraco v6.1 용 FileSystemProvider

Umbraco v6.1 소스의 MediaFileSystem 클래스를 시작점으로 복사했습니다.

그런 다음 /config/FileSystemProviders.config 파일을 편집하여 새 클래스 세부 정보를 삽입했습니다. 내가 Umbraco를 다시 시작하면

, 새 클래스를 호출하지만 오류 얻을 수있다 :

"생성자를 찾을 수 없습니다 유형에 대한 'mysite.core.umbracoExtensions.FileSystemProviders.AzureBlobStorageProvider, mysite.core'0 매개 변수를 사용할 수 "여기

내 클래스의 :

...

[FileSystemProvider("media")] 
public class AzureBlobStorageProvider : FileSystemWrapper 
{ 
    private string rootUrl; 
    CloudStorageAccount storageAccount; 
    CloudBlobClient blobClient; 
    CloudBlobContainer container; 

    public AzureBlobStorageProvider(IFileSystem wrapped) 
     : base(wrapped) 
    { 

     var constring = ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString; 

     // Retrieve storage account from connection string. 
     storageAccount = CloudStorageAccount.Parse(constring); 

     // Create the blob client. 
     blobClient = storageAccount.CreateCloudBlobClient(); 

     // Retrieve reference to a previously created container. 
     container = blobClient.GetContainerReference("mymedia"); 

     //container.CreateIfNotExists(); 
     //container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); 

     rootUrl = "https://mysite.blob.core.windows.net/media"; 
    } 

...

방법

내가 뭘 잘못하고 있는거야?

건배

답변

1

왜 답을 찾을 내가 게시 한 후 다음 곧 찾으려고 시간을 보낼 그것이?

이 문제는 배이되었다

1) 내가 IFileSystem을 구현 했어야 (에 포함되지 않은 매개 변수 이름은 FileSystemProviders.config 파일에서 전달되는 AmazonS3Provider 소스에서 영감)

2)했다 생성자

+2

너깃, 너는 너의 해결책을 나눌 정도로 친절하니? –

+0

@ 스티브, 오래 전에이 답장을 놓친 이유를 모르겠습니다. 그러나 여기에 나오는 다른 사람들의 이익을 위해 File Uploader 컨트롤이 파일 조작에이 클래스를 사용하지 않는다는 것을 발견했기 때문에 FileSystemProvider 사용을 포기했습니다! Azure 웹 사이트 (영구 공유 디스크 있음)를 사용하는 경우 MediaService.Saved 메소드에 연결하여 Azure 저장소로 복사 할 수 있습니다. 또한 MediaService.Deleted 이벤트를 연결했지만 v6.1.6을 설치할 때 발사되지 않는다고 판명되었습니다. 그래서 Trashes 이벤트를 사용하여 편집자가 항목을 휴지통에 다시 업로드해야 함을 의미합니다. – nugget

4

내가 여기 사람들 :

I 설정 신선한 Umbraco의 v6.1.6에서받은 모든 도움을 고려 수행이 반을두고 MediaService.Deleted 이벤트 데피을 확인하지 못했습니다 nitely는 아래 코드로 나를 위해 해고/구부리지 않습니다. 버그를 제출하는 방법을 찾아 보겠습니다 ...

Azure Storage에 Umbraco 미디어 항목을 저장하는 데 관심이있는 다른 사람은 다음과 같습니다. "CDNEnabled"키를 사용하여 이미지 콘텐츠를 표시하기 위해 CDN을 켜고 끌 수 있으며 매번 자신의보기를 터치하지 않고도 "AzureCDNUploadEnabled"키를 사용하여 업로드를 켜고 끌 수 있습니다.

참고로 Azure Blob 저장소의 실제 CDN 부분은 현재 사용할 수 없습니다. 지금은 아니었고 지금도 언젠가는 분명히 다시있을 것입니다.

"AzureCDNCacheControlHeader"값을 설정하여 업로드 할 때 캐시 제어 헤더를 업데이트하여 데이터 사용을 제한하고 이미지 전송 속도를 높일 수 있습니다. 아래의 값은 30 일 후에 만료되도록 이미지를 설정 한 다음 다시 유효성을 검사합니다.

웹에 추가하십시오.구성 appSettings는 노드 :

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

namespace utest1.umbracoExtensions.helpers 
{ 
    public class CDNImage 
    { 
     public static string ConvertUrlToCDN(string source) 
     { 
      if (String.IsNullOrEmpty(source)) 
      { 
       return null; 
      } 

      var cdnUrl = System.Configuration.ConfigurationManager.AppSettings["CDNPath"]; 
      var cdnOn = System.Configuration.ConfigurationManager.AppSettings["CDNEnabled"]; 

      if (cdnOn == "true") 
      { 
       /* 
       * check if the url is absolute or not and whether it should be intercepted - eg. an external image url 
       * if it's absolute you'll need to strip out everything before /media... 
       */ 

       if (source.Contains(GetBaseUrl())) 
       { 
        source = StripBaseUrl(source); 
       } 

      } 

      return source; 
     } 

     private static string GetBaseUrl() 
     { 
      var url = System.Web.HttpContext.Current.Request.Url; 
      var baseUrl = url.Scheme + "//" + url.Host; 

      if (url.Port != 80 && url.Port != 443) 
      { 
       baseUrl += ":" + url.Port; 
      } 

      return baseUrl; 
     } 

     private static string StripBaseUrl(string path) 
     { 
      return path.Replace(GetBaseUrl(), String.Empty); 
     } 
    } 
} 

마지막으로 RazorView에 표시 :

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage 
@{ 
    Layout = "BasePage.cshtml"; 
} 

@using utest1.umbracoExtensions.helpers 

@{ 

    var ms = ApplicationContext.Current.Services.MediaService; 
    var img = ms.GetById(int.Parse(CurrentPage.Image)); 
} 

<h1>Umbraco on Azure is getting there!</h1> 
<p>@img.Name</p> 
<img alt="@img.Name" src="@CDNImage.ConvertUrlToCDN(img.GetValue("umbracoFile").ToString())" /> 

제안

using Microsoft.WindowsAzure.Storage; 
using Microsoft.WindowsAzure.Storage.Blob; 
using System; 
using System.Configuration; 
using System.Web; 
using System.Linq; 
using System.IO; 
using Umbraco.Core; 
using Umbraco.Core.Events; 
using Umbraco.Core.Models; 
using Umbraco.Core.Services; 

namespace utest1.umbracoExtensions.events 
{ 
    public class SaveMediaToAzure : ApplicationEventHandler 
    { 
     /* either add your own logging class or remove this and all calls to 'log' */ 
     private log4net.ILog log = log4net.LogManager.GetLogger(typeof(utest1.logging.PublicLogger)); 

     CloudStorageAccount storageAccount; 
     private string blobContainerName; 
     CloudBlobClient blobClient; 
     CloudBlobContainer container; 
     string cacheControlHeader; 

     private bool uploadEnabled; 

     public SaveMediaToAzure() 
     { 
      try 
      { 
       storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureCDNStorageConnectionString"]); 
       blobContainerName = ConfigurationManager.AppSettings["AzureCDNStorageAccountName"]; 
       blobClient = storageAccount.CreateCloudBlobClient(); 
       container = blobClient.GetContainerReference(ConfigurationManager.AppSettings["AzureCDNBlobContainerName"]); 
       uploadEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["AzureCDNUploadEnabled"]); 
       cacheControlHeader = ConfigurationManager.AppSettings["AzureCDNCacheControlHeader"]; 

       MediaService.Saved += MediaServiceSaved; 
       MediaService.Trashed += MediaServiceTrashed; 
       MediaService.Deleted += MediaServiceDeleted; // not firing 
      } 
      catch (Exception x) 
      { 
       log.Error("SaveMediaToAzure Config Error", x); 
      } 
     } 

     void MediaServiceSaved(IMediaService sender, SaveEventArgs<IMedia> e) 
     { 
      if (uploadEnabled) 
      { 
       foreach (var fileItem in e.SavedEntities) 
       { 
        try 
        { 
         log.Info("Saving media to Azure:" + e.SavedEntities.First().Name); 
         var path = fileItem.GetValue("umbracoFile").ToString(); 
         var filePath = HttpContext.Current.Server.MapPath(path); 

         UploadToAzure(filePath, path); 

         if (fileItem.GetType() == typeof(Umbraco.Core.Models.Media)) 
         { 
          UploadThumbToAzure(filePath, path); 
         } 
        } 
        catch (Exception x) 
        { 
         log.Error("Error saving media to Azure: " + fileItem.Name, x); 
        } 
       } 
      } 
     } 

     /* 
     * Using this because MediaServiceDeleted event is not firing in v6.1.6 
     * 
     */ 

     void MediaServiceTrashed(IMediaService sender, MoveEventArgs<IMedia> e) 
     { 
      if (uploadEnabled) 
      { 
       try 
       { 
        log.Info("Deleting media from Azure:" + e.Entity.Name); 
        var path = e.Entity.GetValue("umbracoFile").ToString(); 
        CloudBlockBlob imageBlob = container.GetBlockBlobReference(StripContainerNameFromPath(path)); 
        imageBlob.Delete(); 
        CloudBlockBlob thumbBlob = container.GetBlockBlobReference(StripContainerNameFromPath(GetThumbPath(path))); 
        thumbBlob.Delete(); 

       } 
       catch (Exception x) 
       { 
        log.Error("Error deleting media from Azure: " + e.Entity.Name, x); 
       } 
      } 

     } 

     /* 
     * MediaServiceDeleted event not firing in v6.1.6 
     * 
     */ 

     void MediaServiceDeleted(IMediaService sender, DeleteEventArgs<IMedia> e) 
     { 
      //if (uploadEnabled) 
      //{ 
      // try 
      // { 
      //  log.Info("Deleting media from Azure:" + e.DeletedEntities.First().Name); 
      //  var path = e.DeletedEntities.First().GetValue("umbracoFile").ToString(); 
      //  CloudBlockBlob imageBlob = container.GetBlockBlobReference(StripContainerNameFromPath(path)); 
      //  imageBlob.Delete(); 
      //  CloudBlockBlob thumbBlob = container.GetBlockBlobReference(StripContainerNameFromPath(GetThumbPath(path))); 
      //  thumbBlob.Delete(); 
      // } 
      // catch (Exception x) 
      // { 
      //  log.Error("Error deleting media from Azure: " + e.DeletedEntities.First().Name, x); 
      // } 
      //} 

      Console.WriteLine(e.DeletedEntities.First().Name); // still not working 

     } 

     private string StripContainerNameFromPath(string path) 
     { 
      return path.Replace("/media/", String.Empty); 
     } 

     /* 
     * 
     * 
     */ 

     private void UploadToAzure(string filePath, string relativePath) 
     { 
      System.IO.MemoryStream data = new System.IO.MemoryStream(); 
      System.IO.Stream str = System.IO.File.OpenRead(filePath); 

      str.CopyTo(data); 
      data.Seek(0, SeekOrigin.Begin); 
      byte[] buf = new byte[data.Length]; 
      data.Read(buf, 0, buf.Length); 

      Stream stream = data as Stream; 

      if (stream.CanSeek) 
      { 
       stream.Position = 0; 
       CloudBlockBlob blob = container.GetBlockBlobReference(StripContainerNameFromPath(relativePath)); 
       blob.UploadFromStream(stream); 
       SetCacheControl(blob); 
      } 
      else 
      { 
       log.Error("Could not read image for upload: " + relativePath); 
      } 
     } 

     private void SetCacheControl(CloudBlockBlob blob) 
     { 
      blob.Properties.CacheControl = cacheControlHeader; 
      blob.SetProperties(); 
     } 

     private void UploadThumbToAzure(string filePath, string relativePath) 
     { 
      var thumbFilePath = GetThumbPath(filePath); 
      var thumbRelativePath = GetThumbPath(relativePath); 
      UploadToAzure(thumbFilePath, thumbRelativePath); 
     } 

     private string GetThumbPath(string path) 
     { 
      var parts = path.Split('.'); 
      var filename = parts[parts.Length - 2]; 
      return path.Replace(filename, filename + "_thumb"); 
     } 

    } 
} 

이것은 RenderHelper입니다 :

<!-- cdn config --> 

    <!-- used for razor rendering --> 
    <add key="CDNPath" value="https://utest.blob.core.windows.net"/> 
    <add key="CDNEnabled" value="true"/> 

    <!-- used for media uploads --> 
    <add key="AzureCDNStorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName={yourAccount};AccountKey={yourKey}"/> 
    <add key="AzureCDNStorageAccountName" value="{yourStorageAccount}"/> 
    <add key="AzureCDNBlobContainerName" value="media"/> 
    <add key="AzureCDNRootUrl" value="https://{yourAccount}.blob.core.windows.net"/> 
    <add key="AzureCDNUploadEnabled" value="true"/> 
    <add key="AzureCDNCacheControlHeader" value="must-revalidate, public, max-age=604800"/> <!-- change to whatever suits you --> 
    <!-- end cdn --> 

이는 이벤트 핸들러입니다 개선을위한 천만에요.

Aaaah, 다시 돌려주는 것이 좋습니다.