You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core AWS Lambda函数无法使用图像处理库的问题排查

解决.NET Core AWS Lambda中图片缩放的跨平台依赖问题

你遇到的核心问题是AWS Lambda的Linux运行环境缺少图形处理库的系统级依赖——不管是CoreCompat.System.Drawing还是SkiaSharp,报错根源都是找不到对应的原生库。下面分两种情况给出解决方案,优先推荐更适配跨平台场景的SkiaSharp方案:

一、优先方案:使用SkiaSharp(无额外系统依赖)

SkiaSharp本身是跨平台设计的,但你遇到的libSkiaSharp找不到问题,大概率是没安装针对Linux的原生资产包,或是发布时被自动剪裁掉了。按以下步骤修复:

1. 安装正确的NuGet包

在项目中安装两个关键包:

dotnet add package SkiaSharp
dotnet add package SkiaSharp.NativeAssets.Linux

SkiaSharp.NativeAssets.Linux会自动包含Linux环境所需的libSkiaSharp.so原生库,无需手动安装系统依赖。

2. 调整项目发布配置

打开你的.csproj文件,添加以下配置,防止发布时剪裁掉原生库(.NET 6+默认启用剪裁功能,会误删原生文件):

<PropertyGroup>
  <!-- 禁用剪裁,保留原生库文件 -->
  <PublishTrimmed>false</PublishTrimmed>
  <!-- 禁用ReadyToRun,避免原生库兼容问题 -->
  <PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup>

3. 完整的SkiaSharp图片缩放示例代码

替换你之前的代码,用SkiaSharp处理S3图片的完整流程:

using SkiaSharp;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Lambda.S3Events;

public async Task FunctionHandler(S3Event s3Event, ILambdaContext context)
{
    var s3Client = new AmazonS3Client();
    
    foreach (var record in s3Event.Records)
    {
        var sourceBucket = record.S3.Bucket.Name;
        var sourceKey = record.S3.Object.Key;
        
        // 跳过已缩放的图片,避免循环处理
        if (sourceKey.StartsWith("resized/")) continue;

        // 从S3获取原始图片
        using var getResponse = await s3Client.GetObjectAsync(sourceBucket, sourceKey);
        using var inputStream = getResponse.ResponseStream;
        
        // 解码图片
        using var originalBitmap = SKBitmap.Decode(inputStream);
        
        // 计算缩放尺寸(保持宽高比)
        const int targetWidth = 100;
        var targetHeight = (int)((float)originalBitmap.Height / originalBitmap.Width * targetWidth);
        
        // 缩放图片(高画质过滤)
        using var scaledBitmap = originalBitmap.Resize(
            new SKImageInfo(targetWidth, targetHeight), 
            SKFilterQuality.High
        );
        
        // 编码为JPEG(可根据需求改为PNG)
        using var scaledImage = SKImage.FromBitmap(scaledBitmap);
        using var outputStream = new MemoryStream();
        scaledImage.Encode(SKEncodedImageFormat.Jpeg, 80).SaveTo(outputStream);
        outputStream.Position = 0;
        
        // 上传缩放后的图片到S3
        var putRequest = new PutObjectRequest
        {
            BucketName = sourceBucket,
            Key = $"resized/{sourceKey}",
            InputStream = outputStream,
            ContentType = "image/jpeg"
        };
        await s3Client.PutObjectAsync(putRequest);
        
        context.Logger.LogInformation($"已完成图片缩放:{sourceKey} -> resized/{sourceKey}");
    }
}

4. 部署注意事项

执行dotnet publish -c Release发布项目,将bin/Release/netX.X/publish目录下的所有文件打包成Zip,上传到Lambda即可。Lambda的Linux运行时会自动加载runtimes/linux-x64/native下的libSkiaSharp.so。


二、兼容方案:修复CoreCompat.System.Drawing(不推荐)

CoreCompat.System.Drawing依赖Windows的GDI+,在Linux环境下需要安装libgdiplus系统库。你可以通过以下两种方式解决:

方式1:使用Docker镜像部署Lambda

创建Dockerfile,在镜像中预装libgdiplus:

# 使用Lambda官方.NET运行时镜像
FROM public.ecr.aws/lambda/dotnet:6

# 安装libgdiplus依赖
RUN yum install -y libgdiplus

# 复制发布后的项目文件到Lambda任务目录
COPY bin/Release/net6.0/publish/ ${LAMBDA_TASK_ROOT}

# 指定Lambda入口函数
CMD ["AwsS3Lambda::AwsS3Lambda.Function::FunctionHandler"]

构建镜像并推送到ECR,再用这个镜像创建Lambda函数即可。

方式2:创建自定义Lambda层

  1. 在本地Linux环境(或WSL)中安装libgdiplus:
    yum install -y libgdiplus
    
  2. 找到libgdiplus.so的路径(通常是/usr/lib64/libgdiplus.so),将其复制到lib/目录下
  3. 将lib/目录打包成Zip,上传为Lambda层
  4. 在你的Lambda函数中添加这个层,运行时就能找到依赖库了

总结

SkiaSharp是更适合Lambda跨平台环境的选择,无需额外配置系统依赖,只需正确安装NuGet包和调整发布配置即可。CoreCompat.System.Drawing因依赖GDI+,需要额外处理系统依赖,维护成本更高,不推荐在Lambda中使用。

内容的提问来源于stack exchange,提问作者Wai Yan Hein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:04:25