Navigation and service panel


Content

This text is fallbacked from the German Version. If you need use Google Translate


Sitecore Upload Watcher erweitern

By Meike Bornand on 10. April 2014, No comments

Ein Kunde hat auf seinem Auftritt eine grosse Anzahl PDF Dateien, die regelmässig aktualisiert werden müssen. Weil dies sehr viel Zeit in Anspruch nimmt, soll die Aktualisierung vereinfacht und möglichst weit automatisiert werden. Mit dem Sitecore Upload Watcher steht ein Tool zur Verfügung, welches die Grundfunktionalitäten des automatisierten Uploads abdeckt.

Durch die Ablage der Files im Ordner upload des Sitecore Webroots wird der Upload von Files in die Sitecore Media Library angestossen. Nun haben wir aber die zusätzliche Anforderung, dass die PDF kategorisiert und mehrsprachig auf Download Seiten angeboten werden sollen. Dies macht es notwendig, dass die Items in der Media Library initial durch die Autoren erstellt und die Kategorien zugewiesen werden. Der Upload Watcher darf deshalb die Items nicht neu erstellen sondern muss so erweitert werden, dass er nur das BLOB in der jeweiligen Sprache ersetzt. Die Files für den Upload werden per FTP ins Filesystem geladen. Ihr Name entspricht dem Item Namen der bereits erstellten Media Items. Die Sprache erkennen wir am Postfix „_lang“. Aus dem Dateinamen können wir also das zu bearbeitende Item und die aktuelle Sprache extrahieren.

Upload Watcher Konfiguration

Den Pfad des Upload Folders können wir in der web.config anpassen:

<sitecore database="SqlServer">
<sc.variable xdt:Transform="Replace" name="mediaFolder" 
value="D:\Data\internet\upload" xdt:Locator="Match(name)"/>
</sitecore>

und den CustomUploadWatcher einbinden:

<system.webServer>
<modules>
<add xdt:Transform="Insert" 
 type="Unic.SitecoreCMS.Internet.CustomCode.Resources.Media.CustomUploadWatcher, 
 Unic.SitecoreCMS.Internet.CustomCode" name="CustomUploadatcher" />
</modules>
</system.webServer>

<system.web>
<httpModules>
<add xdt:Transform="Insert" 
 type="Unic.SitecoreCMS.Internet.CustomCode.Resources.Media.CustomUploadWatcher, 
 Unic.SitecoreCMS.Internet.CustomCode" name="CustomUploadatcher" />
</httpModules>
</system.web>


CustomUploadWatcher

Im CustomUploadWatcher überschreiben wir die beiden Methoden Created und Deleted und bringen den CustomMediaCreator ins Spiel:

protected override void Created(string filePath)
{
  Assert.ArgumentNotNullOrEmpty(filePath, "filePath");
  if (this.IgnoreFile(filePath)) return;
  var creator = new CustomMediaCreator();
  creator.FileCreated(filePath);
}

protected override void Deleted(string filePath)
{
  Assert.ArgumentNotNullOrEmpty(filePath, "filePath");
  if (this.IgnoreFile(filePath)) return;
  var creator = new CustomMediaCreator();
  creator.DeleteItem(filePath);
}


CustomMediaCreator

File hinzufügen

Der CustomMediaCreator erbt vom Sitecore.Resources.Media.MediaCreator und muss die Methode AttachStreamToMediaItem überschreiben, welche in der Basisklasse ein neues MediaItem erstellt, bei uns aber nur das BLOB setzen soll.

Um zu verhindern, dass beim Upload gleichzeitig auf ein Media Item zugegriffen wird, hinterlegen wir das Item während des Bearbeitens in einer SynchronizedCollection. Die Methode TrySetStream wird solange aufgerufen, bis das Item zur frei zur Bearbeitung ist und der Stream erfolgreich gesetzt werden kann.

class CustomMediaCreator : MediaCreator
{
  private static readonly SynchronizedCollection<id> InProcess = new SynchronizedCollection<id>();

  public override Item AttachStreamToMediaItem(Stream stream, string itemPath, string fileName, MediaCreatorOptions options)
  {
    // zu bearbeitendes Item über den Filenamen bestimmen
    Item currentItem = this.GetItem(itemPath, options);

    if (currentItem == null) return null;

    Media media = MediaManager.GetMedia((MediaItem)currentItem);

    var success = false;
    while (success == false)
    {
      success = this.TrySetStream(stream, media, FileUtil.GetExtension(fileName));
    }
    
    return (Item)media.MediaData.MediaItem;
  }


  private bool TrySetStream(Stream stream, Media media, string fileName)
  {
    // Check ob das Item aktuell bearbeitet wird
    if (InProcess.Contains(media.MediaData.MediaItem.ID))
    {
      Log.Info("Item is in Process: " + fileName, this);
      return false;
    }
    // Item vor Zugriff schützen
    InProcess.Add(media.MediaData.MediaItem.ID);

    try
    {
      // BLOB setzen      
      media.SetStream(stream, fileName);
      // Item publizieren
      PublicationUtil.StartAsyncPublication(media.MediaData.MediaItem, false, this);
      // Item wieder freigeben
      InProcess.Remove(media.MediaData.MediaItem.ID); 
      return true;
    }
    catch (Exception ex)
    {
      Log.Error("Error while setting stream from " + fileName + ": " + ex.Message, this);
    }
    finally
    {     
      InProcess.Remove(media.MediaData.MediaItem.ID);
    }
    return false;
  }
}


File Löschen

Wird ein File aus dem Upload Ordner gelöscht, so müssen wir die entsprechenden Sprachversionen des MediaItems in der Methode TryDeleteItemVersion entfernen. Wenn nach dem Löschen der Versionen keine mehr vorhanden sind, wird das Item vollständig gelöscht.

private bool TryDeleteItemVersion(Item item, Language language)
{
  Assert.ArgumentNotNull(item, "item");

  // Check ob das Item aktuell bearbeitet wird
  if (InProcess.Contains(item.ID))
  {
    Log.Info("Item is in Process: " + item.Name, this);
    return false;
  }

  InProcess.Add(item.ID);

  try
  {
     Item languageItem = item.Database.GetItem(item.ID, language, Sitecore.Data.Version.Latest);

     if (languageItem != null)
     {
       // alle Versionen der aktuellen Sprache löschen
       languageItem.Versions.RemoveAll(false);

       // Check ob noch Versionen existieren
       if (!item.Versions.GetVersions(true).Any())
       {
         item.Delete();
       }
     }

     PublicationUtil.StartAsyncPublication(item, false, this);

     InProcess.Remove(item.ID);
     return true;
  }
  catch (Exception ex)
  {
    Log.Error("Error while deleting item  " + item.Name + ": " + ex.Message, this);
  }
  finally
  {
    InProcess.Remove(item.ID);
  }
  return false;
}

No comments

Add your comment

Your email address will not be published. Required fields are marked *

*