使用aws lambda c#裁剪图像(使用Java解决)

时间:2016-12-30 15:23:13

标签: java c# amazon-s3 lambda aws-lambda

我尝试在C#中创建AWS Lambda函数以裁剪存储在S3存储桶中的图像。裁剪后,需要将新图像推送到另一个存储桶。并且必须使用AWS Lambda Client手动调用此函数。作为初学者,网上没有太多的教程,请帮助我。

这就是我的代码的样子

 using System;
 using System.Threading.Tasks;
 using System.IO;

 using Amazon.Lambda.Core;
 using Amazon.Lambda.Serialization;
 using Amazon.S3;
 using Amazon;
 using Amazon.S3.Model;
 using Pomelo.Data.MySql;
 using System.Drawing;
 using Amazon.S3.Transfer;
 //using ImageNet;
 //using ImageResizer;

 // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
 [assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

 namespace Cropper
 {
     public class Crop
     {
         IAmazonS3 s3Client { get; set; }
         private Image orgImg;
         private MySqlConnection dbConn = new MySqlConnection();
         private MySqlCommand cmd = new MySqlCommand(); 

         public Crop()
         {
             s3Client = new AmazonS3Client();
         }

         /*private static string s3AccessKey = Environment.GetEnvironmentVariable("S3AccessKey");
         private static string s3SecretKey = Environment.GetEnvironmentVariable("S3SecretKey");
         private static string s3Region = Environment.GetEnvironmentVariable("S3Region");
         private AmazonS3Client s3Client = new AmazonS3Client(s3AccessKey,s3SecretKey, RegionEndpoint.GetBySystemName(s3Region));
         */

         // public async Task<string> CropImage(string sourceBucket, string key, string destBucket, string permission)
         //public async void CropImage(string sourceBucket, string key, string destBucket, string permission)
         public async Task<string> CropImage(string input, ILambdaContext context)
         {
             s3Client = new AmazonS3Client();

             string[] arr = input.Split(',');
             string sourceBucket = arr[0].Trim();
             string key = arr[1].Trim();
             string destBucket = arr[2].Trim();
             //string size = arr[3].Trim();
             //string crop = arr[3].Trim();
             string permission = arr[3].Trim();

             string path = Path.Combine("/tmp", key);

             try
             {
                 Console.WriteLine("Checkpoint - 0");

                 TransferUtility fileTransferUtility = new TransferUtility(s3Client);
                 TransferUtilityDownloadRequest downloadRequest = new TransferUtilityDownloadRequest();

                 Console.WriteLine("path - " + path);

                 if (File.Exists(path))
                 {
                     File.Delete(path);
                 }
                 downloadRequest.FilePath = path;
                 downloadRequest.BucketName = sourceBucket;
                 downloadRequest.Key = key;
                 fileTransferUtility.Download(downloadRequest);

                 Console.WriteLine("Checkpoint - file transfer");

                 orgImg = Image.FromFile(path);
                 orgImg.RotateFlip(RotateFlipType.Rotate90FlipNone);
                 //FluentImage.FromFile(path)
                 //   .Resize.Width(200)
                 //   .Save("/tmp/test_file.png", OutputFormat.Png);



                 Console.WriteLine("Checkpoint - Img creation");

                 TransferUtilityUploadRequest uploadRequest = new TransferUtilityUploadRequest();
                 //uploadRequest.FilePath = "/tmp/test_file.png";
                 uploadRequest.FilePath = path;
                 uploadRequest.BucketName = destBucket;
                 uploadRequest.Key = key;
                 if (permission.ToUpper() == "PUBLIC")
                 {
                     uploadRequest.CannedACL = S3CannedACL.PublicRead;
                 }
                 else if (permission.ToUpper() == "PRIVATE")
                 {
                     uploadRequest.CannedACL = S3CannedACL.Private;
                 }
                 else if (permission.ToUpper() == "NONE")
                 {
                     uploadRequest.CannedACL = S3CannedACL.NoACL;
                 }
                 fileTransferUtility.Upload(uploadRequest);

                 Console.WriteLine("Checkpoint - Done");

                 return context.AwsRequestId.ToString();
             }
             catch (Exception ex)
             {
                 Console.WriteLine("ex message - " + ex.Message);
                 Console.WriteLine("ex stack - " + ex.StackTrace);
                 return ex.Message;
                 //context.Logger.LogLine(ex.Message);
             }
             finally
             {
                 if (File.Exists(path))
                 {
                     File.Delete(path);
                 }
                 if (orgImg != null)
                 {
                     orgImg.Dispose();
                 }
             }
         }

         //private byte[] ToArrayBytes(Stream input)
         //{
         //    byte[] buffer = new byte[16 * 1024];
         //    using (MemoryStream ms = new MemoryStream())
         //    {
         //        int read;
         //        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
         //        {
         //            ms.Write(buffer, 0, read);
         //        }
         //        return ms.ToArray();
         //    }
         //}

         //private byte[] ImageToByte(Image img)
         //{
         //    ImageConverter converter = new ImageConverter();
         //    return (byte[])converter.ConvertTo(img, typeof(byte[]));
         //}
     }
 }

这是project.json

 {
   "version": "1.0.0-*",
   "buildOptions": {
   },

   "dependencies": {
     "Microsoft.NETCore.App": {
       "type": "platform",
       "version": "1.0.0"
     },
     "Amazon.Lambda.Core": "1.0.0*",
     "Amazon.Lambda.Serialization.Json": "1.0.1",
     "Amazon.Lambda.Tools": {
       "type": "build",
       "version": "1.0.4-preview1"
     },
     "AWSSDK.S3": "3.3.4.1",
     "Pomelo.Data.MySql": "1.0.0",
     "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
     //"System.Drawing-dotnet-core": "1.0.2",
     //"Shaman.System.Drawing": "1.0.1.1",
     //"ZKWeb.System.Drawing": "2.0.1"
     //"System.Drawing.Primitives": "4.3.0"
     //"ImageProcessor-strong-name": "2.3.0",
     //"Microsoft.NETCore.Runtime.CoreCLR": "1.1.0",
     //"Sitecore.ImageProcessor": "1.1.0",
     //"DynamicImage": "3.1.1",
     //"ImageLibrary": "3.0.0",
     //"FluentImage": "1.1.0",
     "CoreCompat.System.Drawing": "1.0.0-beta006",
     "ImageResizer.Mvc": "4.0.5"
     //"NETStandard.Library": "1.6.1"
     //"omu.drawing": "1.0.0"
   },
     "tools": {
       "Amazon.Lambda.Tools": "1.0.4-preview1"
     },
     "frameworks": {
       "netcoreapp1.0": {
         "imports": [
           "dnxcore50",
           "dotnet5.6",
           "net46"
         ]
       }
     }
 }

而且,这是堆栈跟踪

 2017-11-03 23:11:43: START RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb Version: $LATEST
 2017-11-03 23:11:44: Checkpoint - 0
 2017-11-03 23:11:44: path - /tmp/r3_small.jpg
 2017-11-03 23:11:47: Checkpoint - file transfer
 2017-11-03 23:11:47: ex message - The type initializer for 'System.Drawing.GDIPlus' threw an exception.
 2017-11-03 23:11:48: ex stack -    at System.Drawing.GDIPlus.GdipLoadImageFromFile(String filename, IntPtr& image)
 2017-11-03 23:11:48:    at System.Drawing.Image.FromFile(String filename, Boolean useEmbeddedColorManagement)
 2017-11-03 23:11:48:    at System.Drawing.Image.FromFile(String filename)
 2017-11-03 23:11:48:    at Cropper.Crop.<CropImage>d__8.MoveNext()
 2017-11-03 23:11:48: END RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb
 2017-11-03 23:11:48: REPORT RequestId: e3975f78-d1db-11e6-9923-974cd0941dbb    Duration: 4970.70 ms    Billed Duration: 5000 ms    Memory Size: 256 MB Max Memory Used: 63 MB  

用于裁剪和旋转图像的代码

 public void cropLocal( string url, int x, int y, int w, int h, int a)
 {
    try
    {
        if (x != 0 && y != 0 && w != 0 && h != 0)
        {
            if (File.Exists(url))
            {
                orgImg = Image.FromFile(url);
                switch (a)
                {
                    case 90:
                    case -270:
                        orgImg.RotateFlip(RotateFlipType.Rotate90FlipNone);
                        break;
                    case 180:
                    case -180:
                        orgImg.RotateFlip(RotateFlipType.Rotate180FlipNone);
                        break;
                    case 270:
                    case -90:
                        orgImg.RotateFlip(RotateFlipType.Rotate270FlipNone);
                        break;
                }

                if (x < 0) { x = 0; }
                if (y < 0) { y = 0; }
                if (w > orgImg.Width) { w = orgImg.Width; }
                if (h > orgImg.Height) { h = orgImg.Height; }

                bitmap = new Bitmap(orgImg);
                orgImg.Dispose();
                orgImg = null;

                rect = new Rectangle(x, y, w, h);
                cropped = bitmap.Clone(rect, bitmap.PixelFormat);
                bitmap.Dispose();
                bitmap = null;

                //delete original file
                File.Delete(url);
                //Save new file
                cropped.Save(url);
                cropped.Dispose();
                cropped = null;
            }
        }
    }
    catch(Exception ex)
    {
        string excep = ex.Message;
    }
    finally
    {
        if (orgImg != null)
        {
            orgImg.Dispose();
            orgImg = null;
        }
        if (bitmap != null)
        {
            bitmap.Dispose();
            bitmap = null;
        }
        if (cropped != null)
        {
            cropped.Dispose();
            cropped = null;
        }
    }

 }

2 个答案:

答案 0 :(得分:1)

在这个时间点发现C#很难做到这一点,我不得不学习java。请参阅下面的Java代码,从s3下载图像,调整大小(不丢失宽高比),裁剪,旋转和上传到s3(到另一个存储桶)。它运作得很好。

 package imageprocessor;

 import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.util.UUID;

 import javax.imageio.ImageIO;
 import javax.swing.UIManager;

 import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
 import com.amazonaws.services.lambda.runtime.Context;
 import com.amazonaws.services.lambda.runtime.RequestHandler;
 import com.amazonaws.services.s3.AmazonS3Client;
 import com.amazonaws.services.s3.model.CannedAccessControlList;
 import com.amazonaws.services.s3.model.GetObjectRequest;
 import com.amazonaws.services.s3.model.PutObjectRequest;


 public class LambdaImageProcessor implements RequestHandler<String, String> {

    private static final String filePath = "/tmp/";
    private static File localFile, outputfileCropped, outputfileRotated, outputfileSized;
     private static final float xsize = 500;   //max width for resize
     private static final float ysize = 500;   //max height for resize

     @Override
     public String handleRequest(String input, Context context) {

        AmazonS3Client s3Client = new AmazonS3Client(
                 new DefaultAWSCredentialsProviderChain());

         context.getLogger().log("Input: " + input + "\n");

         try
         {
            String[] arr = input.split(",");
            String sourceBucket = arr[0];
            String key = arr[1];
             String destBucket = arr[2];
             String permission = arr[3];

            //download
             context.getLogger().log("AWS S3 downloading image\n");
            GetObjectRequest downloadReq = new GetObjectRequest(sourceBucket, key);

            String uniqueID = UUID.randomUUID().toString().replaceAll("-", "");
            localFile = new File(filePath + uniqueID + "_" + key);
            outputfileCropped = new File(filePath + uniqueID + "_" + "c_" + key);
            outputfileRotated = new File(filePath + uniqueID + "_" + "r_" + key);
            outputfileSized = new File(filePath + uniqueID + "_" + "s_" + key);

            if(localFile.exists())
            {
                localFile.delete();
            }
            if(outputfileCropped.exists())
            {
                outputfileCropped.delete();
            }
            if(outputfileRotated.exists())
            {
                outputfileRotated.delete();
            }

            context.getLogger().log("File name - " + localFile.toString() + "\n");
            s3Client.getObject(downloadReq, localFile);      
            context.getLogger().log("AWS S3 download - Done\n");

            //upload
            if(localFile.exists())
            {
                //context.getLogger().log("AWS S3 cropping image\n");

                BufferedImage bufferedImage = ImageIO.read(localFile);  

                BufferedImage resizeBuffered = resizeImage(bufferedImage, xsize, ysize);
                //ImageIO.write(resizeBuffered, "jpg", outputfileSized);    
                context.getLogger().log("AWS S3 Resize - Done\n");

                Rectangle rect = new Rectangle(100, 100, 300, 150);
                BufferedImage cropBuffered = cropImage(resizeBuffered, rect);
                context.getLogger().log("AWS S3 Crop - Done\n");

                ImageIO.write(rotateImage(cropBuffered, 90), "jpg", outputfileRotated);
                context.getLogger().log("AWS S3 Rotate - Done\n");

                context.getLogger().log("AWS S3 uploading image\n");
                PutObjectRequest uploadReq = new PutObjectRequest(destBucket, key, outputfileRotated);        

                if(permission.toUpperCase().equals("PUBLIC"))
                {
                    uploadReq.setCannedAcl(CannedAccessControlList.PublicRead);
                }
                else if(permission.toUpperCase().equals("PRIVATE"))
                {
                    uploadReq.setCannedAcl(CannedAccessControlList.Private);
                }
                s3Client.putObject(uploadReq);
                context.getLogger().log("AWS S3 upload - Done\n");
            }
            else
            {
                context.getLogger().log("Downloaded file not found\n");
            }
            return context.getAwsRequestId();
         }
         catch (Exception ex)
         {
            context.getLogger().log("Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString() + "\n");
            return "Exception - " + ex.getMessage().toString() + " " + ex.getStackTrace().toString();
         }
         finally 
         {          
            if(localFile.exists())
            {
                localFile.delete();
                context.getLogger().log("Temp Local File Deleted\n");
            }  
            if(outputfileCropped.exists())
            {
                outputfileCropped.delete();
                context.getLogger().log("Temp Cropped File Deleted\n");
            }
            if(outputfileRotated.exists())
            {
                outputfileRotated.delete();
                context.getLogger().log("Temp Rotated File Deleted\n");
            }
            if(outputfileSized.exists())
            {
                outputfileSized.delete();
                context.getLogger().log("Temp ReSized File Deleted\n");
            }
        }
     }

     private static BufferedImage cropImage(BufferedImage src, Rectangle rect) {
       BufferedImage dest = src.getSubimage(rect.x, rect.y, rect.width, rect.height);
       return dest; 
    }

     private static BufferedImage rotateImage(BufferedImage bufferedImage, int angle) { 

        double theta = Math.toRadians(angle);
        double cos = Math.abs(Math.cos(theta));
         double sin = Math.abs(Math.sin(theta));
         double width  = bufferedImage.getWidth();
         double height = bufferedImage.getHeight();
         int w = (int)(width * cos + height * sin);
         int h = (int)(width * sin + height * cos);

         BufferedImage out = new BufferedImage(w, h, bufferedImage.getType());
         Graphics2D g2 = out.createGraphics();
         g2.setPaint(UIManager.getColor("Panel.background"));
         g2.fillRect(0,0,w,h);
         double x = w/2;
         double y = h/2;
         AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
         x = (w - width)/2;
         y = (h - height)/2;
         at.translate(x, y);
         g2.drawRenderedImage(bufferedImage, at);
         g2.dispose();
         return out; 
    }

     private static BufferedImage resizeImage(BufferedImage bufferedImage, float sizeX, float sizeY)
    {
        float ratioX = sizeX / bufferedImage.getWidth();
        float ratioY = sizeY / bufferedImage.getHeight();
        float ratio = Math.min(ratioX, ratioY);

        float newX = bufferedImage.getWidth() * ratio;
        float newY = bufferedImage.getHeight() * ratio;

        BufferedImage resizedImage = new BufferedImage((int)newX, (int)newY, bufferedImage.getType());
         Graphics2D g = resizedImage.createGraphics();
         g.drawImage(bufferedImage, 0, 0, (int)newX, (int)newY, null);
         g.dispose();

         return resizedImage;

    }

 }

答案 1 :(得分:0)

您需要了解如何read an S3 object using the .NET SDK

您需要learn how to upload an image to S3 using the .NET SDK

您可以在测试或主要方法中练习这两个没有AWS Lambda集成的操作,让您的脚步受到影响。

接下来,您想知道how to crop an image in C#。您可以再次测试,无需AWS Lambda。

最后,您应该阅读AWS Lambda C# documentation并尝试一些创建函数的简单示例。获得一个完全正常工作的基本示例,然后在上面添加您已经开发的代码中进行扩展。