我尝试在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;
}
}
}
答案 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并尝试一些创建函数的简单示例。获得一个完全正常工作的基本示例,然后在上面添加您已经开发的代码中进行扩展。