2016-04-26 15 views
1

Ich versuche C# Azure WebJob zu erstellen, der bei einer neuen Blob-Erstellung ausgelöst wird, um das hochgeladene Bild in drei verschiedenen Größen zu skalieren. Ich fand und folgte diesem großartigen tutorial.Azure WebJobs Blob-Auslöser - mehrere Größenanpassungen

Es gibt zwei Abschnitte, der erste Teil "funktioniert", tritt aber in eine Rekursionsschleife ein, da die Erstellung der drei neuen Größen das Skript auslöst, das drei weitere Instanzen für jedes der drei neuen Bilder erstellt, usw. und so weiter . Dies war beabsichtigt, um die Notwendigkeit der endgültigen Umsetzung hervorzuheben. Hier

ist der anfängliche Rekursionsschleife Code der "Werke" Lage in der Functions.cs Datei:

public static void ResizeImagesW800([BlobTrigger("input/{name}.{ext}")] Stream input, 
    [Blob("output/{name}-w800.{ext}", FileAccess.Write)] Stream output) 
{ 
    ResizeImage(input, output, 800); 
} 

public static void ResizeImagesW500([BlobTrigger("input/{name}.{ext}")] Stream input, 
    [Blob("output/{name}-w500.{ext}", FileAccess.Write)] Stream output) 
{ 
    ResizeImage(input, output, 500); 
} 

private static void ResizeImage(Stream input, Stream output, int width) 
{ 
    var instructions = new Instructions 
    { 
     Width = width, 
     Mode = FitMode.Carve, 
     Scale = ScaleMode.Both 
    }; 
    ImageBuilder.Current.Build(new ImageJob(input, output, instructions)); 
} 

Hier ist der Code, den Visual Studio 2015 gibt einen Fehler auf:

public static void ResizeImagesTask(
    [BlobTrigger("input/{name}.{ext}")] Stream inputBlob, 
    string name, 
    string ext, 
    IBinder binder) 
{ 
    int[] sizes = { 800, 500, 250 }; 
    var inputBytes = inputBlob.CopyToBytes(); 
    foreach (var width in sizes) 
    { 
     var input = new MemoryStream(inputBytes); 
     var output = binder.Bind<Stream>(new BlobAttribute($"output/{name}-w{width}.{ext}", FileAccess.Write)); 

     ResizeImage(input, output, width); 
    } 
} 

private static void ResizeImage(Stream input, Stream output, int width) 
{ 
    var instructions = new Instructions 
    { 
     Width = width, 
     Mode = FitMode.Carve, 
     Scale = ScaleMode.Both 
    }; 
    ImageBuilder.Current.Build(new ImageJob(input, output, instructions)); 
} 

der Fehler wird an dieser Linie geworfen:

var inputBytes = inputBlob.CopyToBytes(); 

der Fehler ist:

012.351.
CS1061: 'Stream' does not contain a definition for 'CopyToBytes' and no extension method 'CopyToBytes' accepting a first argument of type 'Stream' could be found (are you missing a using directive or an assembly reference?) 

Ich habe versucht mit .NET 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1 als Zielframeworks, aber alle von ihnen werfen den gleichen Fehler.

Auch hier sind die Verwendung von Aussagen für die Functions.cs Datei:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.Azure.WebJobs; 
using Microsoft.WindowsAzure.Storage; 
using ImageResizer; 

Was mache ich falsch hier? Vielen Dank!

UPDATE 1

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Web; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.Azure.WebJobs; 
using Microsoft.WindowsAzure.Storage; 
using ImageResizer; 
using ImageResizer.ExtensionMethods; 
using Microsoft.WindowsAzure.Storage.Blob; 

namespace HilcoIndustrialAssetApiWebJob 
{ 
    public class Functions 
    { 
     // output blolb sizes 
     private static readonly int[] Sizes = { 800, 500, 250 }; 

     public static void ResizeImagesTask(
     [QueueTrigger("newfileuploaded")] string filename, 
     [Blob("input/{queueTrigger}", FileAccess.Read)] Stream blobStream, 
     [Blob("output")] CloudBlobContainer container) 
     { 
      // Extract the filename and the file extension 
      var name = Path.GetFileNameWithoutExtension(filename); 
      var ext = Path.GetExtension(filename); 

      Console.WriteLine("New Blob name -> " + name); 

      // Get the mime type to set the content type 
      var mimeType = MimeMapping.GetMimeMapping(filename); 

      foreach (var width in Sizes) 
      { 
       // Set the position of the input stream to the beginning. 
       blobStream.Seek(0, SeekOrigin.Begin); 

       // Get the output stream 
       var outputStream = new MemoryStream(); 
       ResizeImage(blobStream, outputStream, width); 

       // Get the blob reference 
       var blob = container.GetBlockBlobReference($"{name}_{width}.{ext}"); 

       // Set the position of the output stream to the beginning. 
       outputStream.Seek(0, SeekOrigin.Begin); 
       blob.UploadFromStream(outputStream); 

       // Update the content type => don't know if required 
       blob.Properties.ContentType = mimeType; 
       blob.SetProperties(); 
      } 
     } 

     private static void ResizeImage(Stream input, Stream output, int width) 
     { 
      var instructions = new Instructions 
      { 
       Width = width, 
       Mode = FitMode.Carve, 
       Scale = ScaleMode.Both 
      }; 
      var imageJob = new ImageJob(input, output, instructions); 

      // Do not dispose the source object 
      imageJob.DisposeSourceObject = false; 
      imageJob.Build(); 
     } 
    } 
} 
+0

Sie diesen Beitrag gesehen haben http://stackoverflow.com/questions/7238018/getting-stream-does-not-support-writing-exception-in Der folgende Code? – Thomas

+0

Brian, ich habe Ihre Frage bearbeitet, um den azurblauen Blobspeicher mit einem Tag zu versehen. – Thomas

+0

Brian, möchten Sie den Titel Ihres Posts in etwas wie diesen umbenennen: Azure WebJobs Blob Trigger - mehrere Größen? – Thomas

Antwort

2

Ich denke, das ImageResizer NuGet Paket Gebrauch Probe. Sie können es von VS2015 mit dem Befehl Install-Package ImageResizer installieren. Wenn Sie dann mit ImageResizer.ExtensionMethods hinzufügen; In Ihrem Code erhalten Sie die CopyToBytes-Methode, die das Stream-Objekt erweitert. this helps Mit freundlichen Grüßen Stéphane

+0

danke, das hat den Fehler tatsächlich behoben. Obwohl der Code jetzt kompiliert und in Azure veröffentlicht werden kann, wird beim Triggern des Triggers ein Fehler angezeigt. Aktualisiert meine Frage mit der Protokolldatei, irgendwelche Vorschläge? Nochmals vielen Dank für die schnelle Lösung! –

0

Azure Webjob SDK Unterstützung Blob Bindung, so dass Sie direkt an einen Klecks binden kann.

In Ihrem Kontext möchten Sie an einen Eingabeblob binden und mehrere Ausgabeblobs erstellen.

  • Verwenden Sie die BlobTriggerAttribute für den Eingang.
  • Verwenden Sie die BlobTriggerAttribute, um an Ihre Ausgabeblobs zu binden. Da Sie mehrere Ausgabeblobs erstellen möchten, können Sie direkt an den Ausgabebehälter binden.

Der Code Ihrer ausgelöst Funktion kann so aussehen:

using System.IO; 
using System.Web; 
using ImageResizer; 
using Microsoft.Azure.WebJobs; 
using Microsoft.WindowsAzure.Storage.Blob; 

public class Functions 
{ 
    // output blolb sizes 
    private static readonly int[] Sizes = {800, 500, 250}; 

    public static void ResizeImage(
     [BlobTrigger("input/{name}.{ext}")] Stream blobStream, string name, string ext 
     , [Blob("output")] CloudBlobContainer container) 
    { 
     // Get the mime type to set the content type 
     var mimeType = MimeMapping.GetMimeMapping($"{name}.{ext}"); 
     foreach (var width in Sizes) 
     { 
      // Set the position of the input stream to the beginning. 
      blobStream.Seek(0, SeekOrigin.Begin); 

      // Get the output stream 
      var outputStream = new MemoryStream(); 
      ResizeImage(blobStream, outputStream, width); 

      // Get the blob reference 
      var blob = container.GetBlockBlobReference($"{name}-w{width}.{ext}"); 

      // Set the position of the output stream to the beginning. 
      outputStream.Seek(0, SeekOrigin.Begin); 
      blob.UploadFromStream(outputStream); 

      // Update the content type 
      blob.Properties.ContentType = mimeType; 
      blob.SetProperties(); 
     } 
    } 

    private static void ResizeImage(Stream input, Stream output, int width) 
    { 
     var instructions = new Instructions 
     { 
      Width = width, 
      Mode = FitMode.Carve, 
      Scale = ScaleMode.Both 
     }; 
     var imageJob = new ImageJob(input, output, instructions); 

     // Do not dispose the source object 
     imageJob.DisposeSourceObject = false; 
     imageJob.Build(); 
    } 
} 

Beachten Sie die Verwendung des DisposeSourceObject auf dem ImageJob Objekt, so dass wir mehrere Zeit der BLOB-Stream lesen kann.

Darüber hinaus sollten Sie einen Blick auf die Webjob Dokumentation haben über BlobTrigger: How to use Azure blob storage with the WebJobs SDK

Die WebJobs SDK Scans Log-Dateien für neue oder geänderte Blobs zu beobachten. Dieser Prozess ist nicht Echtzeit; Eine Funktion wird möglicherweise erst einige Minuten oder länger nach der Erstellung des Blobs ausgelöst. Zusätzlich storage logs are created on a "best efforts" Basis; Es gibt keine Garantie, dass alle Ereignisse erfasst werden. Unter bestimmten Umständen könnten Protokolle verloren gehen. Wenn die Geschwindigkeits- und Zuverlässigkeitseinschränkungen von Blob-Triggern für Ihre Anwendung nicht akzeptabel sind, wird empfohlen, beim Erstellen des Blobs eine Warteschlangennachricht zu erstellen und das Attribut QueueTrigger anstelle des Attributs BlobTrigger für die Funktion zu verwenden, die den Blob verarbeitet.

So könnte es besser sein, Nachricht aus einer Warteschlange auszulösen, die nur die Dateinamen senden, können Sie automatisch den Eingang Blob an die Nachrichtenwarteschlange binden:

using System.IO; 
using System.Web; 
using ImageResizer; 
using Microsoft.Azure.WebJobs; 
using Microsoft.WindowsAzure.Storage.Blob; 

public class Functions 
{ 
    // output blolb sizes 
    private static readonly int[] Sizes = { 800, 500, 250 }; 

    public static void ResizeImagesTask1(
     [QueueTrigger("newfileuploaded")] string filename, 
     [Blob("input/{queueTrigger}", FileAccess.Read)] Stream blobStream, 
     [Blob("output")] CloudBlobContainer container) 
    { 
     // Extract the filename and the file extension 
     var name = Path.GetFileNameWithoutExtension(filename); 
     var ext = Path.GetExtension(filename); 

     // Get the mime type to set the content type 
     var mimeType = MimeMapping.GetMimeMapping(filename); 

     foreach (var width in Sizes) 
     { 
      // Set the position of the input stream to the beginning. 
      blobStream.Seek(0, SeekOrigin.Begin); 

      // Get the output stream 
      var outputStream = new MemoryStream(); 
      ResizeImage(blobStream, outputStream, width); 

      // Get the blob reference 
      var blob = container.GetBlockBlobReference($"{name}-w{width}.{ext}"); 

      // Set the position of the output stream to the beginning. 
      outputStream.Seek(0, SeekOrigin.Begin); 
      blob.UploadFromStream(outputStream); 

      // Update the content type => don't know if required 
      blob.Properties.ContentType = mimeType; 
      blob.SetProperties(); 
     } 
    } 

    private static void ResizeImage(Stream input, Stream output, int width) 
    { 
     var instructions = new Instructions 
     { 
      Width = width, 
      Mode = FitMode.Carve, 
      Scale = ScaleMode.Both 
     }; 
     var imageJob = new ImageJob(input, output, instructions); 

     // Do not dispose the source object 
     imageJob.DisposeSourceObject = false; 
     imageJob.Build(); 
    } 
} 
+0

Wow Thomas, danke für die offensichtlich gut durchdachte und informierte Antwort. Ich überprüfe jetzt und werde bald zurückkommen! –

+0

Prost, lassen Sie mich wissen, wenn Sie weitere Informationen benötigen. – Thomas

+0

Da hast du lol angeboten. Ich vermute, dass Sie ein NuGet-Paket oder .NET für die MimeMapping-Klasse verwendet haben, oder mache ich etwas anderes falsch, um den Fehler "existiert nicht in diesem Kontext" zu erhalten? –

0

Ich habe ein Webjob Projekt mit VS2015 erstellt (immer noch in update1), verwende ich Azure 2.8 SDK (ich werde es bald auf 2.9 aktualisieren).

Ich habe einen Schnitt & einfügen mit dem Beispielcode von Ihrem ursprünglichen Link. Ich habe die beiden Verbindungszeichenfolgen für die Anwendungskonfiguration hinzugefügt (und die entsprechenden Web Connection-Verbindungszeichenfolgen in den Anwendungseinstellungen aktualisiert). Ich habe juste das referenzierte Nugget-Paket und das fehlende "using" hinzugefügt. Es funktioniert gut.

Ich habe den Beispielcode auf GitHub veröffentlicht, falls Sie es ausprobieren möchten.

https://github.com/stephgou/ImageResizer.git

Sie müssen nur die App config und Ihre Web-App-Verbindungszeichenfolgen aktualisieren.

this helps

Mit freundlichen Grüßen Stéphane

Verwandte Themen