【发布时间】:2018-05-25 14:21:58
【问题描述】:
我正在使用 C# Dot NET Core 开发一个 AWS Lambda 函数项目。我现在正在做的是在将图像文件上传到 s3 时调整图像大小。这是我的项目结构。
我在单一解决方案中有三个项目。 AwsLambda.Domain 项目是 Dot NET Framework 项目,AwsLambda 是 Dot NET Core 项目。 Aws Lambda 项目依赖于 AwsLambda.Domain 项目。基本上,在 AwsLambda.Domain 项目中,我创建了一个名为 ImageHelper.cs 的新类,它负责使用 Dot NET Framework 中的功能调整图像大小。
这是我在 AwsLambda.Doamin 项目下的 ImageHelper.cs 类。
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace AwsS3Lambda.Domain
{
public class ImageHelper
{
public string CreateThumbImage(string sourcePath, string destPath, int width, int height)
{
Image imgOriginal = Image.FromFile(sourcePath);
Image imgActual = Scale(imgOriginal, width, height);
imgActual.Save(destPath);
imgActual.Dispose();
return destPath;
}
private Image Scale(Image imgPhoto, int width, int height)
{
float sourceWidth = imgPhoto.Width;
float sourceHeight = imgPhoto.Height;
float destHeight = 0;
float destWidth = 0;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
// force resize, might distort image
if(width != 0 && height != 0)
{
destWidth = width;
destHeight = height;
}
// change size proportially depending on width or height
else if(height != 0)
{
destWidth = (float)(height * sourceWidth) / sourceHeight;
destHeight = height;
}
else
{
destWidth = width;
destHeight = (float)(sourceHeight * width / sourceWidth);
}
Bitmap bmPhoto = new Bitmap((int)destWidth, (int)destHeight,
PixelFormat.Format32bppPArgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, (int)destWidth, (int)destHeight),
new Rectangle(sourceX, sourceY, (int)sourceWidth, (int)sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
}
}
这是我的 lambda 函数类,它使用 ImageHelper.cs 类来调整上传图像的大小。
public class Function
{
public static string IAM_KEY { get { return "xxx"; } }
public static string IAM_SECRET { get { return "xxx"; } }
public static string TEMP_IMG_FILE_PATH { get { return @"../../tmp/temp_img.jpeg"; } }
public static string TEMP_RESIZED_IMG_PATH { get { return @"../../tmp/resized_img.jpeg"; } }
private IAmazonS3 S3Client { get; set; }
private ImageHelper imageHelper { get; set; }
public Function()
{
S3Client = new AmazonS3Client();
imageHelper = new ImageHelper();
}
public Function(IAmazonS3 s3Client)
{
this.S3Client = s3Client;
this.imageHelper = new ImageHelper();
}
public async Task<string> FunctionHandler(S3Event evnt, ILambdaContext context)
{
var s3Event = evnt.Records?[0].S3;
if(s3Event == null)
{
return null;
}
try
{
if(s3Event.Object.Key.ToLower().Contains("thumb"))
{
//Console.WriteLine("The image is already a thumb file");
return "The file is aready a thumb image file";
}
string[] pathSegments = s3Event.Object.Key.Split('/');
string eventCode = pathSegments[0];
string userEmail = pathSegments[1];
string filename = pathSegments[2];
string extension = Path.GetExtension(filename); //.jpeg with "dot"
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);
using(var objectResponse = await this.S3Client.GetObjectAsync(s3Event.Bucket.Name, s3Event.Object.Key))
{
using(Stream responseStream = objectResponse.ResponseStream)
{
this.saveFile(responseStream, Function.TEMP_IMG_FILE_PATH);
imageHelper.CreateThumbImage(Function.TEMP_IMG_FILE_PATH, Function.TEMP_RESIZED_IMG_PATH, 200, 200);
///This code is throwing error
await this.S3Client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
{
BucketName = s3Event.Bucket.Name,
Key = fileNameWithoutExtension + ".thumb" + extension,
FilePath = Function.TEMP_RESIZED_IMG_PATH
});
}
}
return "Thumbnail version of the image has been created";
}
catch(Exception e)
{
context.Logger.LogLine($"Error getting object {s3Event.Object.Key} from bucket {s3Event.Bucket.Name}. Make sure they exist and your bucket is in the same region as this function.");
context.Logger.LogLine(e.Message);
context.Logger.LogLine(e.StackTrace);
throw;
}
}
private void saveFile(Stream stream, string path)
{
using(var fileStream = File.Create(path))
{
//stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
}
}
}
当我在控制台中测试该函数时,它给了我这个关于在 AwsLambda.Domain 项目(Dot NET Framework)下实现的图像大小调整功能的错误。
{
"errorType": "AggregateException",
"errorMessage": "One or more errors occurred. (Could not load type 'System.Drawing.Image' from assembly 'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.)",
"stackTrace": [
"at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)",
"at lambda_method(Closure , Stream , Stream , LambdaContextInternal )"
],
"cause": {
"errorType": "TypeLoadException",
"errorMessage": "Could not load type 'System.Drawing.Image' from assembly 'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.",
"stackTrace": [
"at AwsS3Lambda.Domain.ImageHelper.CreateThumbImage(String sourcePath, String destPath, Int32 width, Int32 height)",
"at AwsS3Lambda.Function.<FunctionHandler>d__18.MoveNext() in C:\\Users\\Acer\\Documents\\Visual Studio 2017\\Projects\\AwsS3Lambda\\AwsS3Lambda\\Function.cs:line 106"
]
},
"causes": [
{
"errorType": "TypeLoadException",
"errorMessage": "Could not load type 'System.Drawing.Image' from assembly 'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.",
"stackTrace": [
"at AwsS3Lambda.Domain.ImageHelper.CreateThumbImage(String sourcePath, String destPath, Int32 width, Int32 height)",
"at AwsS3Lambda.Function.<FunctionHandler>d__18.MoveNext() in C:\\Users\\Acer\\Documents\\Visual Studio 2017\\Projects\\AwsS3Lambda\\AwsS3Lambda\\Function.cs:line 106"
]
}
]
}
为什么会抛出那个错误。当我在 ASP.NET MVC 项目中使用图像大小调整类代码时,它正在工作。它只是不适用于这个 AWS Lambda 函数项目。我的项目中缺少什么?在基于 Dot NET Core 的 AWS Lambda 函数项目中调整上传图像大小的另一种方法是什么?
【问题讨论】:
-
在亚马逊上你只能使用 .NET Core。您不能使用常规的 .NET Framework。你需要一个库来manipulate .NET Core 下的图像。
-
所以。你的意思是我不能使用 System.Drawing?我也将 SkiaSharp 库用于 .net 核心。它给出了这个错误,“SkiaSharp.SKAbstractManagedStream”的类型初始化程序引发了异常。
-
我也将绘图 dll 用于核心版本。不工作。无法使用任何已安装的 nuget 图像库。问题可能是因为 AWS lambda 使用的是 linux 并且需要一些依赖项。
标签: c# amazon-web-services amazon-s3 .net-core aws-lambda