在coldfusion 11中使用imagereadbase64()读取大图像时出现“java.lang.outofmemoryerror:java堆空间”

2jcobegt  于 2021-07-11  发布在  Java
关注(0)|答案(1)|浏览(366)

我有一个简单的restapi内置在coldfusion11中,允许我们的供应商更新产品信息。它们发送的大多数数据(大约30个属性)都是简单的值—字符串和数字。一个属性是表示图像文件的base64编码字符串。restapi更新数据库中的简单数据值,然后读取图像并将其调整为适合在网站上使用的4个大小。我注意到,有时供应商会发送带有一些请求(20mb+)的大图像,这些请求通常会在 ImageReadBase64() 函数被调用。我们在这个服务器上运行了其他的web应用程序,似乎处理这些图像时被锁定的内存也会导致这些应用程序出现问题。我正在尝试找出代码中是否有什么可以减少这些问题的方法,即使是找到一种方法,如果图像“太大”(超过一定大小),就不处理它们。以下是运行以处理图像的所有代码:

public struct function getDimensionsToEnlarge(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric minWidth,
    required numeric minHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    if  (   ARGUMENTS.minHeight > 0
        &&  ARGUMENTS.minWidth > 0
        &&  ARGUMENTS.imageHeight < ARGUMENTS.minHeight
        &&  ARGUMENTS.imageWidth < ARGUMENTS.minWidth
        ) {
        LOCAL.Dimensions.width=ARGUMENTS.minWidth;
        LOCAL.Dimensions.height=ARGUMENTS.minHeight;
    }

    return LOCAL.Dimensions;
}

public struct function getDimensionsToShrink(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric maxWidth,
    required numeric maxHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    if  (   ARGUMENTS.maxHeight > 0
        &&  ARGUMENTS.maxWidth > 0
        &&  (   ARGUMENTS.imageHeight > ARGUMENTS.maxHeight
            ||  ARGUMENTS.imageWidth > ARGUMENTS.maxWidth
            )
        ) {
        LOCAL.Dimensions.width=ARGUMENTS.maxWidth;
        LOCAL.Dimensions.height=ARGUMENTS.maxHeight;
    }

    return LOCAL.Dimensions;
}

public struct function getDimensionsToFit(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric minWidth,
    required numeric minHeight,
    required numeric maxWidth,
    required numeric maxHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    LOCAL.Dimensions =
        getDimensionsToEnlarge(
            imageHeight=ARGUMENTS.imageHeight,
            imageWidth=ARGUMENTS.imageWidth,
            minWidth=ARGUMENTS.minWidth,
            minHeight=ARGUMENTS.minHeight
            );

    if (LOCAL.Dimensions.width < 0 && LOCAL.Dimensions.height < 0)
        LOCAL.Dimensions =
            getDimensionsToShrink(
                imageHeight=ARGUMENTS.imageHeight,
                imageWidth=ARGUMENTS.imageWidth,
                maxWidth=ARGUMENTS.maxWidth,
                maxHeight=ARGUMENTS.maxHeight
                );

    return LOCAL.Dimensions;
}

public any function scale(
    required any image,
    string action="fit",
    numeric minWidth=-1,
    numeric minHeight=-1,
    numeric maxWidth=-1,
    numeric maxHeight=-1
    ) {
    LOCAL.Dimensions={
            width=-1,
            height=-1
        };
    LOCAL.Image=Duplicate(ARGUMENTS.image);

    switch (ARGUMENTS.action) {
        case "shrink":
            LOCAL.Dimensions =
                getDimensionsToShrink(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    maxWidth=ARGUMENTS.maxWidth,
                    maxHeight=ARGUMENTS.maxHeight
                );

            break;
        case "enlarge":
            LOCAL.Dimensions =
                getDimensionsToEnlarge(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    minWidth=ARGUMENTS.minWidth,
                    minHeight=ARGUMENTS.minHeight
                );

            break;
        default:
            LOCAL.Dimensions =
                getDimensionsToFit(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    minWidth=ARGUMENTS.minWidth,
                    minHeight=ARGUMENTS.minHeight,
                    maxWidth=ARGUMENTS.maxWidth,
                    maxHeight=ARGUMENTS.maxHeight
                );

            break;
    }

    if (LOCAL.Dimensions.width > 0 && LOCAL.Dimensions.height > 0) {
        ImageSetAntialiasing(LOCAL.Image, "on");

        ImageScaleToFit(
            LOCAL.Image,
            LOCAL.Dimensions.width,
            LOCAL.Dimensions.height
            );
    }

    return LOCAL.Image;
}

public void function createLargeThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=500, maxWidth=700),
        getLargeImagePath(),
        0.75,
        true
        );

    return;
}

public void function createMediumThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=300, maxWidth=300),
        getMediumImagePath(),
        0.75,
        true
        );

    return;
}

public void function createSmallThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=50, maxWidth=50),
        getSmallImagePath(),
        0.75,
        true
        );

    return;
}

public void function createMobileThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=50, maxWidth=300),
        getMobileImagePath(),
        0.75,
        true
        );

    return;
}

public void function createProductThumbnails(required any image) {
    createLargeThumbnail(argumentCollection=ARGUMENTS);
    createMediumThumbnail(argumentCollection=ARGUMENTS);
    createSmallThumbnail(argumentCollection=ARGUMENTS);
    createMobileThumbnail(argumentCollection=ARGUMENTS);

    return;
}

createProductThumbnails(ImageReadBase64(ARGUMENTS.ImageUpload));

我需要做些什么来启动垃圾回收吗?
谢谢你的帮助!

vulvrdjw

vulvrdjw1#

你在打电话吗 scale() 四次(每次 createXXXThumbnail() ),有效地将内存使用率提高了四倍,因为 duplicate() 通过参数传递的图像对象。你也打电话给本地人 ImageScaleToFit() 使用昂贵的默认插值四次,这可能会在内部创建另一个字节数组。因此,看起来无辜的20MB在处理过程中很容易膨胀到160MB甚至更多。

相关问题