Aws-lambda-dotnet: рдХреНрдпрд╛ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред libgdiplus рдХреЗ рд╕рд╛рде рдЖрдордВрддреНрд░рдг рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 18 рдЕрдкреНрд░реИрд▓ 2018  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: aws/aws-lambda-dotnet

рд╕реБрдиреЛ,

рдореИрдВрдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдЕрдкрдиреЗ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ .NET рдХреЛрд░ 2 рдПрдкреАрдЖрдИ рдореЗрдВ рдХреИрдкреНрдЪрд╛ рдкреАрдврд╝реА рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИред рдореИрдВ рд╢рдкрде рд▓реЗ рд╕рдХрддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдПрдХ рд╕рдордп рдореЗрдВ рдЪрд▓ рд░рд╣рд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рд╡рд┐рдлрд▓ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдореИрдВрдиреЗ рд╡рд░реНрддрдорд╛рди рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рджреЗрдЦрд╛ рд╣реИред .NET рдХреЛрд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛; рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЬреЛ рдореИрдВ рдкрдврд╝ рд░рд╣рд╛ рд╣реВрдБ, рдЙрд╕рд╕реЗ GDI+ рдкрд░ рд╕реНрдкрд╖реНрдЯ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдЗрд╕реЗ рдмрдирд╛рддреА рд╣реИрдВ рддрд╛рдХрд┐ рдпрд╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕рдВрдЧрдд рди рд╣реЛред рдЖрдЧреЗ рдХреА рдЬрд╛рдВрдЪ рдХреЗ рдмрд╛рдж, рдПрдХ CompatCore.System.Drawing рд╣реИ рдЬрд┐рд╕реЗ рдореВрд▓ рд░реВрдк рд╕реЗ рдореЛрдиреЛ рдЯреАрдо рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ System.Drawing рдХрд╛ рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ GDI+ рдХреЗ Linux рдЖрдзрд╛рд░рд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ; рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХреЗрд╡рд▓ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐/рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдЙрдард╛рддрд╛ рд╣реИ:

System.TypeInitializationException: The type initializer for 'System.Drawing.GDIPlus' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'gdiplus': The specified module or one of its dependencies could not be found.
 (Exception from HRESULT: 0x8007007E)
   at System.Drawing.GDIPlus.GdiplusStartup(UInt64& token, GdiplusStartupInput& input, GdiplusStartupOutput& output)
   at System.Drawing.GDIPlus..cctor()
   --- End of inner exception stack trace ---
   at System.Drawing.GDIPlus.GdipCreateBitmapFromScan0(Int32 width, Int32 height, Int32 stride, PixelFormat format, IntPtr scan0, IntPtr& bmp)
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
   at Ivy.Captcha.Services.CaptchaGenerationService.GenerateCaptchaImage(Int32 captchaCharLength, Int32 width, Int32 height)
   at IAGE.Api.Data.Services.CaptchaApiService.GenerateCaptcha() in D:\Workspaces\iam-global-education\src\Api\IAGE.Api.Data\Services\CaptchaApiService.cs:line 63
   at lambda_method.lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Elmah.Io.AspNetCore.ElmahIoMiddleware.d__6.MoveNext()

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реВрддреНрд░ рдХреЗ рдЕрдиреБрд╕рд╛рд░: https://github.com/CoreCompat/CoreCompat/issues/3

рдореБрдЭреЗ рд░рдирдЯрд╛рдЗрдо.рд▓рд┐рдирдХреНрд╕-x64.CoreCompat.System.Drawing NuGet рдкреИрдХреЗрдЬ рдЬреЛрдбрд╝рдХрд░ libgdiplus DLL рд░реЗрдлрд░реА рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛; рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд┐рд╕реА рдХрд╛рдо рдХрд╛ рдирд╣реАрдВ рдерд╛ред рдореИрдВ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕рдВрджрд░реНрднреЛрдВ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╕рдВрдпреЛрдЬрдиреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╕рдорд╛рди рдореБрджреНрджрд╛ рд╣реЛрдЧрд╛ рдЬрд┐рд╕реЗ рдХрдИ рд▓реЛрдЧреЛрдВ рдиреЗ System.Cryptography.x509Certificates рдХреЗ рд╕рд╛рде рджреЗрдЦрд╛ рд╣реИ; рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рддрдХ рдРрд╕рд╛ рд╕рдВрдпреЛрдЬрди рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рджреЗ рд░рд╣рд╛ рд╣реЛред

рдХреНрдпрд╛ рдХреЛрдИ рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рдкрд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рдФрд░ рдЪрд▓рд╛рдирд╛?

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рд╣рд╛рдБ Magick.NET рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреЛ рдорд╣реАрдиреЗ рдкрд╣рд▓реЗ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдореБрдЭреЗ рдмрд╕ рдЗрд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рдерд╛ред рдиреАрдЪреЗ рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдЫрд╡рд┐ рдердВрдмрдиреЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдерд╛ред

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.1.0" />
    <PackageReference Include="Amazon.Lambda.S3Events" Version="1.0.2" />
    <PackageReference Include="AWSSDK.S3" Version="3.3.16.2" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.1.0-beta" />
    <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.4.2" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.1.1" />
  </ItemGroup>

</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.XRay.Recorder.Core;
using ImageMagick;

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

namespace ImageResizer
{
    public class Function
    {
        IAmazonS3 S3Client { get; set; }

        /// <summary>
        /// Default constructor. This constructor is used by Lambda to construct the instance. When invoked in a Lambda environment
        /// the AWS credentials will come from the IAM role associated with the function and the AWS region will be set to the
        /// region the Lambda function is executed in.
        /// </summary>


        public Function()
        {
            Amazon.XRay.Recorder.Handlers.AwsSdk.AWSSDKHandler.RegisterXRayForAllServices();
            S3Client = new AmazonS3Client();
        }

        /// <summary>
        /// Constructs an instance with a preconfigured S3 client. This can be used for testing the outside of the Lambda environment.
        /// </summary>
        /// <param name="s3Client"></param>
        public Function(IAmazonS3 s3Client)
        {
            this.S3Client = s3Client;
        }

        HashSet<string> SupportedImageTypes { get; } = new HashSet<string> { ".png", ".jpg", ".jpeg" };

        /// <summary>
        /// This method is called for every Lambda invocation. This method takes in an S3 event object and can be used 
        /// to respond to S3 notifications.
        /// </summary>
        /// <param name="evnt"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task FunctionHandlerAsync(S3Event evnt, ILambdaContext context)
        {
            foreach (var record in evnt.Records)
            {
                var bucket = record.S3.Bucket.Name;
                var key = record.S3.Object.Key;

                if (key.StartsWith("thumbnails"))
                {
                    context.Logger.LogLine($"Object s3://{bucket}/{key} is already a thumbnail");
                    continue;
                }
                if (!SupportedImageTypes.Contains(Path.GetExtension(key.ToLower())))
                {
                    context.Logger.LogLine($"Object s3://{bucket}/{key} is not a supported image type");
                    continue;
                }

                context.Logger.LogLine($"Processing s3://{bucket}/{key}");

                MemoryStream resizedImageStream;
                using (var response = await this.S3Client.GetObjectAsync(bucket, key))
                {
                    AWSXRayRecorder.Instance.BeginSubsegment("Magick Image Resize");
                    try
                    {
                        using (MagickImageCollection collection = new MagickImageCollection(response.ResponseStream))
                        {
                            foreach (MagickImage image in collection)
                            {
                                image.Resize(200, 200);
                            }
                            context.Logger.LogLine($"   Image resized");

                            resizedImageStream = new MemoryStream();
                            collection.Write(resizedImageStream);
                            resizedImageStream.Position = 0;
                        }
                    }
                    catch(Exception e)
                    {
                        AWSXRayRecorder.Instance.AddException(e);
                        throw;
                    }
                    finally
                    {
                        AWSXRayRecorder.Instance.EndSubsegment();
                    }
                }

                var index = key.LastIndexOf('/');
                var thumbnailKey = "thumbnails/" + (index != -1 ? key.Substring(index + 1) : key);
                await this.S3Client.PutObjectAsync(new PutObjectRequest
                {
                    BucketName = bucket,
                    Key = thumbnailKey,
                    InputStream = resizedImageStream
                });

                context.Logger.LogLine($"   Thumbnail saved to s3://{bucket}/{thumbnailKey}");
            }
        }
    }
}

рд╕рднреА 7 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореИрдВрдиреЗ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд▓рд┐рдП libgdiplus рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реБрдирд╛ рд╣реИред Linux рдкрд░ рдЖрд░реЗрдЦрдг рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдпрд╛ рдирд╣реАрдВ рд╣реИред рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдЫрд╡рд┐ рд╣реЗрд░рдлреЗрд░ рдХреЗ рд▓рд┐рдП рдореИрдВ Magick.NET-Q16-AnyCPU рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдХреЛрдИ рдЪрд┐рддреНрд░ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рд╣реИ рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХреИрдкреНрдЪрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдореЗрдВ рдХреБрдЫ рдбреНрд░рд╛рдЗрдВрдЧ рдХреНрд╖рдорддрд╛рдПрдВ рд╣реИрдВ ред

рдореЗрд░реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рдкреНрд░рддреАрдд рд╣реЛрддреА рд╣реИ рдХрд┐ рд▓реИрдореНрдмреНрдбрд╛ рд▓рд┐рдирдХреНрд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкрд░ libgdiplus рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдерд╛рдкрдирд╛ рдирд╣реАрдВ рд╣реИред рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐, рд░рдирдЯрд╛рдЗрдо.рд▓рд┐рдирдХреНрд╕-x64.CoreCompat.System.Drawing рдПрдХ NuGet рдкреИрдХреЗрдЬ рдерд╛, рдЬреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░ apt-get рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рдерд╛; рд╣рд╛рд▓рд╛рдВрдХрд┐, рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд▓рд┐рдВрдХ рдкрд░ рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдореЗрдВ рдЦреЛрджрдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рдпрд╣ рд╕рдордЭрдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде рд╣реВрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЕрд╕рдлрд▓ рдХреНрдпреЛрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

https://github.com/CoreCompat/CoreCompat/tree/master/native/runtime.linux-x64.CoreCompat.System.Drawing

рдореИрдВ рдЕрднреА рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП рдЪрд╛рд░реЛрдВ рдУрд░ рдЦреБрджрд╛рдИ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреВрдВрдЧрд╛; рд▓реЗрдХрд┐рди, рд╡рд╣ Magick.NET рд▓рд┐рдВрдХ рдХреБрдЫ рдХреИрдкреНрдЪрд╛ рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╡реИрдз рддрд░реАрдХрд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдлреЙрд▓рдмреИрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд░рдЦрдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рджреВрдВрдЧрд╛ред рдореИрдВрдиреЗ рдореВрд▓ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдбреНрд░рд╛рдЗрдВрдЧ рдХреЛ рдмреЗрд╣рддрд░ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рд╕рдВрдЧрддрддрд╛ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рднреА рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдЬреАрдбреАрдЖрдИ + рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ,

рдЖрдкрдиреЗ рдЗрд╕ Magick.NET рдкреИрдХреЗрдЬ рдХреЛ рд▓реИрдореНрдмреНрдбрд╛ рдкрд░ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдЙрдкрдпреЛрдЧ рд╣реЛрддреЗ рджреЗрдЦрд╛ рд╣реИ?

рд╣рд╛рдБ Magick.NET рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреЛ рдорд╣реАрдиреЗ рдкрд╣рд▓реЗ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдореБрдЭреЗ рдмрд╕ рдЗрд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рдерд╛ред рдиреАрдЪреЗ рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдЫрд╡рд┐ рдердВрдмрдиреЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдерд╛ред

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.1.0" />
    <PackageReference Include="Amazon.Lambda.S3Events" Version="1.0.2" />
    <PackageReference Include="AWSSDK.S3" Version="3.3.16.2" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.1.0-beta" />
    <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.4.2" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.1.1" />
  </ItemGroup>

</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.XRay.Recorder.Core;
using ImageMagick;

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

namespace ImageResizer
{
    public class Function
    {
        IAmazonS3 S3Client { get; set; }

        /// <summary>
        /// Default constructor. This constructor is used by Lambda to construct the instance. When invoked in a Lambda environment
        /// the AWS credentials will come from the IAM role associated with the function and the AWS region will be set to the
        /// region the Lambda function is executed in.
        /// </summary>


        public Function()
        {
            Amazon.XRay.Recorder.Handlers.AwsSdk.AWSSDKHandler.RegisterXRayForAllServices();
            S3Client = new AmazonS3Client();
        }

        /// <summary>
        /// Constructs an instance with a preconfigured S3 client. This can be used for testing the outside of the Lambda environment.
        /// </summary>
        /// <param name="s3Client"></param>
        public Function(IAmazonS3 s3Client)
        {
            this.S3Client = s3Client;
        }

        HashSet<string> SupportedImageTypes { get; } = new HashSet<string> { ".png", ".jpg", ".jpeg" };

        /// <summary>
        /// This method is called for every Lambda invocation. This method takes in an S3 event object and can be used 
        /// to respond to S3 notifications.
        /// </summary>
        /// <param name="evnt"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task FunctionHandlerAsync(S3Event evnt, ILambdaContext context)
        {
            foreach (var record in evnt.Records)
            {
                var bucket = record.S3.Bucket.Name;
                var key = record.S3.Object.Key;

                if (key.StartsWith("thumbnails"))
                {
                    context.Logger.LogLine($"Object s3://{bucket}/{key} is already a thumbnail");
                    continue;
                }
                if (!SupportedImageTypes.Contains(Path.GetExtension(key.ToLower())))
                {
                    context.Logger.LogLine($"Object s3://{bucket}/{key} is not a supported image type");
                    continue;
                }

                context.Logger.LogLine($"Processing s3://{bucket}/{key}");

                MemoryStream resizedImageStream;
                using (var response = await this.S3Client.GetObjectAsync(bucket, key))
                {
                    AWSXRayRecorder.Instance.BeginSubsegment("Magick Image Resize");
                    try
                    {
                        using (MagickImageCollection collection = new MagickImageCollection(response.ResponseStream))
                        {
                            foreach (MagickImage image in collection)
                            {
                                image.Resize(200, 200);
                            }
                            context.Logger.LogLine($"   Image resized");

                            resizedImageStream = new MemoryStream();
                            collection.Write(resizedImageStream);
                            resizedImageStream.Position = 0;
                        }
                    }
                    catch(Exception e)
                    {
                        AWSXRayRecorder.Instance.AddException(e);
                        throw;
                    }
                    finally
                    {
                        AWSXRayRecorder.Instance.EndSubsegment();
                    }
                }

                var index = key.LastIndexOf('/');
                var thumbnailKey = "thumbnails/" + (index != -1 ? key.Substring(index + 1) : key);
                await this.S3Client.PutObjectAsync(new PutObjectRequest
                {
                    BucketName = bucket,
                    Key = thumbnailKey,
                    InputStream = resizedImageStream
                });

                context.Logger.LogLine($"   Thumbnail saved to s3://{bucket}/{thumbnailKey}");
            }
        }
    }
}

рдореИрдВ рдЕрднреА рдореИрдЬрд┐рдХ рдореЗрдВ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЦреВрдмрд╕реВрд░рддреА рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рди рдХреЗрд╡рд▓ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╡рд┐рд╡рд┐рдз рдЫрд╡рд┐ рд╣реЗрд░рдлреЗрд░ рдПрдкреАрдЖрдИ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕рдорд░реНрдерд┐рдд рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред рд╕реБрдЭрд╛рд╡ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рдж, рдереЛрдбрд╝рд╛ рдФрд░ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдпрд╛рд╕ рдФрд░ рдореБрдЭреЗ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдЗрд╕ рдмрд╛рдзрд╛ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП!

рдореИрдВ рдЕрднреА рднреА рдЙрддреНрд╕реБрдХ рд╣реВрдВ рдХрд┐ рдХреИрд╕реЗ рдХреБрдЫ рд▓реЛрдЧ рдЬреАрдбреАрдЖрдИ + рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдКрдкрд░ рдФрд░ рдЪрд▓рд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ рдЧрдП рд╣реИрдВред рдореБрдЭреЗ рдРрд╕рд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рд░рдирдЯрд╛рдЗрдо рдирд┐рд╖реНрдкрд╛рджрди рд╕реЗ рдкрд╣рд▓реЗ рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдЙрдкрдпреБрдХреНрдд libgdiplus рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рд╣реЛ рд╕рдХреЗред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ ImageMagick Drawables API рдареАрдХ рд╕реЗ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ AWS рд▓реИрдореНрдмреНрдбрд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рд╣реИ рдЬреЛ рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдБред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдФрд░ рдбреНрд░рд╛ () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдкрд░, рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддреНрд░реБрдЯрд┐ рдЙрдард╛ рд░рд╣рд╛ рд╣реВрдВ:

ImageMagick.MagickDrawErrorException: NonconformingDrawingPrimitiveDefinition `text' @ error/draw.c/DrawImage/3402
   at ImageMagick.MagickExceptionHelper.Check(IntPtr exception)
   at ImageMagick.DrawingWand.NativeDrawingWand.Render()
   at ImageMagick.MagickImage.Draw(IEnumerable`1 drawables)
   at Ivy.Captcha.Magick.Services.MagickCaptchaGenerationService.GenerateCaptchaImage(Int32 captchaCharLength, Int32 width, Int32 height)
   at IAGE.Api.Data.Services.CaptchaApiService.GenerateCaptcha() in D:\Workspaces\iam-global-education\src\Api\IAGE.Api.Data\Services\CaptchaApiService.cs:line 63
   at lambda_method.lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Elmah.Io.AspNetCore.ElmahIoMiddleware.d__6.MoveNext()

рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реВрдВ, рдореБрдЭреЗ рд▓реИрдореНрдмреНрдбрд╛ рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдбреНрд░рд╛рдЗрдВрдЧ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдирд╣реАрдВ рдорд┐рд▓ рд░рд╣реА рд╣реИред рдореИрдВрдиреЗ System.Drawing (Microsoft), CoreCompat.System.Drawing (рдореЛрдиреЛ), рдФрд░ ImageMagick (рддреГрддреАрдп рдкрдХреНрд╖) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рднреА рдХрд╛ рдХреЛрдИ рдлрд╛рдпрджрд╛ рдирд╣реАрдВ рд╣реБрдЖред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЫрд╡рд┐ рдирд┐рд░реНрдорд╛рдг рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдХреБрдЫ рдкреНрд░рдореБрдЦ рд╕рд┐рд╕реНрдЯрдо рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдореБрдЭреЗ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рдХреЗ рд╕рд╛рде рдХрдард┐рди рд╕рдордп рдорд┐рд▓ рд░рд╣рд╛ рд╣реИред рдЕрдЧрд░ рдореБрдЭреЗ рд╕рдлрд▓рддрд╛ рдорд┐рд▓рддреА рд╣реИ рддреЛ рдореИрдВ рдкреНрд░рдпреЛрдЧ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреВрдВрдЧрд╛ рдФрд░ рд╡рд╛рдкрд╕ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░реВрдВрдЧрд╛ред

рдХреНрдпрд╛ рдХреЛрдИ рдореМрдХрд╛ рд╣реИ рдХрд┐ рд╣рдо рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЕрдкрдиреЗ рд▓реИрдореНрдмреНрдбрд╛ рд░рдирдЯрд╛рдЗрдо рдХреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдХрд╕реНрдЯрдорд╛рдЗрдЬрд╝ рдХрд░ рдкрд╛рдПрдВрдЧреЗ рдЬреИрд╕реЗ рд╣рдо рдбреЙрдХрд░ рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЛ рдХрд╕реНрдЯрдорд╛рдЗрдЬрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рд╕рдм рдореЗрд░реЗ рд▓реИрдореНрдмреНрдбрд╛ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдореЗрдВ libgdiplus рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдореИрдВ рдПрдХ рдмреЗрд╡рдХреВрдл рд╣реВрдВ рдФрд░ рдореБрдЭреЗ рдХрднреА рднреА рдЕрдкрдиреЗ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рд╕рд░реНрд╡рд░ рдкрд░ рдХреИрдкреНрдЪрд╛ рдЫрд╡рд┐рдпрд╛рдВ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдереА рдЬрдм рдореИрдВ рдХреЗрд╡рд▓ Google рд░реАрдХреИрдкреНрдЪрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рдерд╛ред рдЗрд╕ рддрд░рд╣ рдореЗрд░рд╛ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рдХреЗрд╡рд▓ рд╕рддреНрдпрд╛рдкрди рдХреЛрдб рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИ рдФрд░ рдХрднреА рднреА рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рдбреНрд░рд╛рдЗрдВрдЧ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред

рдореИрдВ рдЕрднреА рднреА рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рд▓реИрдореНрдмреНрдбрд╛ рдкрд░ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреА рдбреНрд░рд╛рдЗрдВрдЧ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдПрдХ рд╡рд┐рдзрд┐ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ; рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмреИрдХ рдмрд░реНрдирд░ рдкрд░ рд░рдЦрдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЗрд╕ рд╕рдордп рдореЗрд░реА рдУрд░ рд╕реЗ рдПрдХ рднрдпрд╛рдирдХ рдбрд┐рдЬрд╛рдЗрди рдирд┐рд░реНрдгрдп рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдЪрд╛рдХ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рд╢рд╛рдпрдж рд▓реИрдореНрдмреНрдбрд╛ рдХреА рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдкрд░рддреЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рддрдм рддрдХ рдХрд░ рд╕рдХрддреА рд╣реИрдВ рдЬрдм рддрдХ рдХрд┐ рдХрд┐рд╕реА рдмрд┐рдВрджреБ рдкрд░ рдиреЗрдЯ рдХреЛрд░ рдореЗрдВ рдЙрдЪрд┐рдд рд╕рдорд░реНрдерди рдЙрдкрд▓рдмреНрдз рди рд╣реЛред

https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

lehoangphan picture lehoangphan  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ljacobsson picture ljacobsson  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

scionwest picture scionwest  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

bslatner picture bslatner  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

CrazyBaran picture CrazyBaran  ┬╖  7рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ