最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)Base64圖片轉(zhuǎn)URL的完整方案

 更新時(shí)間:2025年11月05日 10:34:49   作者:很少更新  
這篇文章主要介紹了如何使用Java實(shí)現(xiàn)Base64格式圖片轉(zhuǎn)換為可訪問的URL鏈接的過程,包括數(shù)據(jù)有效性校驗(yàn)、圖片壓縮、方向信息校正以及阿里云OSS存儲(chǔ)對(duì)接,核心實(shí)現(xiàn)代碼涵蓋了從獲取Base64圖片數(shù)據(jù)到上傳OSS的完整流程,需要的朋友可以參考下

一、功能概述

本方案實(shí)現(xiàn)將前端傳遞的Base64格式圖片轉(zhuǎn)換為可訪問的URL鏈接,核心功能包含:

  • Base64數(shù)據(jù)有效性校驗(yàn)
  • 圖片壓縮(轉(zhuǎn)換WebP格式+質(zhì)量調(diào)整)
  • Exif方向信息自動(dòng)校正
  • 阿里云OSS存儲(chǔ)對(duì)接
  • 完整的異常處理機(jī)制

二、核心實(shí)現(xiàn)代碼

1.獲取Base64圖片數(shù)據(jù)

首先,我們從JSON對(duì)象中獲取Base64編碼的圖片數(shù)據(jù),并檢查其是否為空或?yàn)榭兆址?/p>

String base64Image = param.getString("base64");
if (base64Image == null || base64Image.isEmpty()) {
    throw new IllegalArgumentException("Base64 image data is missing");
}

2 .移除數(shù)據(jù)前綴

Base64編碼的圖片數(shù)據(jù)通常包含一個(gè)前綴,例如 “data:image/png;base64,”。我們需要移除這個(gè)前綴以獲取純Base64數(shù)據(jù)。

String[] parts = base64Image.split(",");
if (parts.length != 2) {
    throw new IllegalArgumentException("Invalid base64 image data");
}
byte[] imageBytes = Base64.getDecoder().decode(parts[1]);

3.創(chuàng)建臨時(shí)文件

將字節(jié)數(shù)組寫入臨時(shí)文件,以便后續(xù)處理。

File tempFile = File.createTempFile("tempImage", ".jpg");
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
    fos.write(imageBytes);
}

4.轉(zhuǎn)換圖片格式

使用ImageIO和WebPWriteParam將圖片轉(zhuǎn)換為WebP格式,并進(jìn)行壓縮。

ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();
writer.setOutput(new FileImageOutputStream(newFile));
WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
writeParam.setCompressionMode(WebPWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType(writeParam.getCompressionTypes()[0]);
writeParam.setCompressionQuality(0.1f);
BufferedImage image = ImageIO.read(new FileInputStream(tempFile));
writer.write(null, new IIOImage(image, null, null), writeParam);
writer.dispose();

5.調(diào)整圖片方向

根據(jù)圖片的EXIF信息調(diào)整圖片方向(可選)。

Metadata metadata = ImageMetadataReader.readMetadata(tempFile);
ExifIFD0Directory exifDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
if (exifDir != null && exifDir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
    orientation = exifDir.getInt(ExifIFD0Directory.TAG_ORIENTATION);
}
switch (orientation) {
    case 6:  // 順時(shí)針旋轉(zhuǎn)90度
        image = rotateImage(image, 90);
        break;
    case 3:  // 旋轉(zhuǎn)180度
        image = rotateImage(image, 180);
        break;
    case 8:  // 逆時(shí)針旋轉(zhuǎn)90度
        image = rotateImage(image, 270);
        break;
}

6.上傳到OSS

使用OssTemplate將轉(zhuǎn)換后的圖片上傳到OSS。

7… 返回文件URL

上傳完成后,返回文件的URL地址。

三、關(guān)鍵技術(shù)點(diǎn)解析

1. Base64數(shù)據(jù)處理

  • 數(shù)據(jù)校驗(yàn):通過split(“,”)分離數(shù)據(jù)頭與有效數(shù)據(jù)
  • 字節(jié)解碼:使用Java8+內(nèi)置Base64解碼器
  • 大小記錄:記錄原始圖片大小用于監(jiān)控

2. 圖片壓縮優(yōu)化

參數(shù)作用說明
壓縮格式WebP相比JPEG節(jié)省30%空間
壓縮質(zhì)量0.1f質(zhì)量與文件大小的平衡點(diǎn)
壓縮模式EXPLICIT顯式控制壓縮參數(shù)

3. Exif方向校正

iOS等設(shè)備拍攝的照片可能包含方向標(biāo)記,常見情況:

  • 6:手機(jī)豎拍(需要順時(shí)針旋轉(zhuǎn)90°)
  • 3:倒置拍攝(旋轉(zhuǎn)180°)
  • 8:逆時(shí)針90°拍攝(旋轉(zhuǎn)270°)

4. OSS上傳優(yōu)化

  • 臨時(shí)文件機(jī)制:避免內(nèi)存溢出風(fēng)險(xiǎn)
  • 自動(dòng)清理:finally塊確保刪除臨時(shí)文件
  • 命名策略:時(shí)間戳+隨機(jī)數(shù)保證唯一性

四、性能對(duì)比測(cè)試

對(duì)1920x1080的JPEG圖片處理結(jié)果:

處理階段文件大小耗時(shí)
原始圖片2.3MB-
WebP壓縮后680KB420ms
質(zhì)量調(diào)整+旋轉(zhuǎn)210KB520ms

五、最佳實(shí)踐建議

  1. 壓縮質(zhì)量調(diào)整:根據(jù)業(yè)務(wù)場(chǎng)景在0.1-0.3之間調(diào)整
  2. 異常監(jiān)控:添加OSS上傳失敗重試機(jī)制
  3. 內(nèi)存優(yōu)化:使用try-with-resources管理流
  4. 擴(kuò)展方向
    • 添加CDN緩存頭設(shè)置
    • 對(duì)接圖片審核服務(wù)
    • 實(shí)現(xiàn)分布式文件存儲(chǔ)

六、常見問題排查

Q1 圖片上傳后方向仍然錯(cuò)誤?

  • 檢查Exif讀取是否被其他程序修改
  • 驗(yàn)證旋轉(zhuǎn)算法與實(shí)際設(shè)備的匹配情況

Q2 壓縮后圖片質(zhì)量不理想?

  • 調(diào)整setCompressionQuality參數(shù)
  • 改用有損+無損混合壓縮模式

Q3 OSS鏈接無法訪問?

  • 檢查Bucket讀寫權(quán)限設(shè)置
  • 驗(yàn)證OSS Endpoint配置
  • 確認(rèn)網(wǎng)絡(luò)防火墻策略

七、完整代碼示例

public String convertUrl(JSONObject param) {
        // 從JSON對(duì)象中獲取Base64編碼的圖片數(shù)據(jù)
        String base64Image = param.getString("base64");
        //獲取base64的大小
        // 檢查Base64圖片數(shù)據(jù)是否為空或?yàn)榭兆址?
        if (base64Image == null || base64Image.isEmpty()) {
            throw new IllegalArgumentException("Base64 image data is missing");
        }
//        log.info("base64Image:{}",base64Image);
        // 移除數(shù)據(jù)前綴 "data:image/png;base64,"
        String[] parts = base64Image.split(",");
        // 檢查Base64數(shù)據(jù)是否包含兩部分(前綴和數(shù)據(jù))
        if (parts.length != 2) {
            throw new IllegalArgumentException("Invalid base64 image data");
        }
        // 解碼Base64數(shù)據(jù)為字節(jié)數(shù)組
        byte[] imageBytes = Base64.getDecoder().decode(parts[1]);
        int size=imageBytes.length/ 1024;
        log.info("壓縮前的圖片大小為:"+size+"KB");
        // 生成帶有前綴 "pic" 和時(shí)間戳的文件名
        String fileName = "pic_" + System.currentTimeMillis() + ".webp";
        try {
            // 將字節(jié)數(shù)組轉(zhuǎn)換為InputStream
            //對(duì)照片進(jìn)行壓縮 改成webp格式 再上傳
            try {
                // 創(chuàng)建臨時(shí)文件
                File tempFile = File.createTempFile("tempImage", ".jpg");
                File newFile = File.createTempFile("tempImage", ".webp");
                // 將ByteArrayInputStream的內(nèi)容寫入到臨時(shí)文件中
                try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                    fos.write(imageBytes);
                }
                // 使用臨時(shí)文件創(chuàng)建FileImageOutputStream
                ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();
                writer.setOutput(new FileImageOutputStream(newFile));
                WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
                writeParam.setCompressionMode(WebPWriteParam.MODE_EXPLICIT);
                writeParam.setCompressionType(writeParam.getCompressionTypes()[0]);
                writeParam.setCompressionQuality(0.1f);
                //ImageIO 讀取 tempFile
                InputStream inputStream = new FileInputStream(tempFile);
                //判斷圖片方向
                BufferedImage image = ImageIO.read(inputStream);
                int orientation = 1;
                try {
                    Metadata metadata = ImageMetadataReader.readMetadata(tempFile);
                    ExifIFD0Directory exifDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                    if (exifDir != null && exifDir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
                        orientation = exifDir.getInt(ExifIFD0Directory.TAG_ORIENTATION);
                    }
                    log.info("圖片方向?yàn)椋簕}",orientation);
                    // 根據(jù)方向調(diào)整圖片(可選)
                    switch (orientation) {
                        case 6:  // 順時(shí)針旋轉(zhuǎn)90度
                            image = rotateImage(image, 90);
                            break;
                        case 3:  // 旋轉(zhuǎn)180度
                            image = rotateImage(image, 180);
                            break;
                        case 8:  // 逆時(shí)針旋轉(zhuǎn)90度
                            image = rotateImage(image, 270);
                            break;
                        // 其他情況保持原樣
                    }
                } catch (Exception e) {
                    log.warn("讀取Exif信息失敗", e);
                }
                if (image == null) {
                    throw new IllegalArgumentException("Invalid image data");
                }
                writer.write(null, new IIOImage(image, null, null), writeParam);
                writer.dispose();
                // 使用OssTemplate將文件上傳到OSS
                ossTemplate.putObject("xxxxx", fileName, new FileInputStream(newFile));
                //獲取臨時(shí)文件大小
                int fileSize= (int) (newFile.length()/1024);
                log.info("壓縮后的圖片大小為:"+fileSize+"KB");
                // 刪除臨時(shí)文件
                tempFile.delete();
                newFile.delete();
            } catch (IOException e) {
                log.error("Error occurred while compressing and uploading image", e);
                throw new RuntimeException("Failed to compress and upload image", e);
            }
            // 返回文件的URL地址
            return ossTemplate.getObjectURL("xxxxx", fileName);
        } catch (Exception e) {
            log.error("Error occurred while converting base64 image to URL", e);
            throw new RuntimeException("Failed to convert base64 image to URL", e);
        }
    }
    // 輔助方法:旋轉(zhuǎn)圖片
    private static BufferedImage rotateImage(BufferedImage image, int degrees) {
        AffineTransform transform = new AffineTransform();
        transform.rotate(Math.toRadians(degrees), image.getWidth()/2, image.getHeight()/2);
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        return op.filter(image, null);
    }

到此這篇關(guān)于Java實(shí)現(xiàn)Base64圖片轉(zhuǎn)URL的完整方案的文章就介紹到這了,更多相關(guān)Java Base64圖片轉(zhuǎn)URL內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java?Executors常用線程池

    java?Executors常用線程池

    這篇文章主要為大家介紹了java?Executors中提供的幾種常用的線程池使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java實(shí)現(xiàn)簡(jiǎn)單密碼加密功能

    Java實(shí)現(xiàn)簡(jiǎn)單密碼加密功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單密碼加密功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Java責(zé)任鏈模式定義與用法分析

    Java責(zé)任鏈模式定義與用法分析

    這篇文章主要介紹了Java責(zé)任鏈模式定義與用法,結(jié)合具體實(shí)例分析了java責(zé)任鏈模式的功能、定義、使用方法、適用情況等,需要的朋友可以參考下
    2017-06-06
  • Java String、StringBuffer與StringBuilder的區(qū)別

    Java String、StringBuffer與StringBuilder的區(qū)別

    本文主要介紹Java String、StringBuffer與StringBuilder的區(qū)別的資料,這里整理了相關(guān)資料及詳細(xì)說明其作用和利弊點(diǎn),有需要的小伙伴可以參考下
    2016-09-09
  • Spring實(shí)戰(zhàn)之注入集合值操作示例

    Spring實(shí)戰(zhàn)之注入集合值操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之注入集合值操作,結(jié)合實(shí)例形式分析了Spring注入集合值相關(guān)配置及使用操作技巧,需要的朋友可以參考下
    2019-11-11
  • Java實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送

    Java實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送

    這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送的相關(guān)資料,實(shí)例講解了java郵件發(fā)送實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下
    2016-02-02
  • QR 二維碼中插入圖片實(shí)現(xiàn)方法

    QR 二維碼中插入圖片實(shí)現(xiàn)方法

    這篇文章主要介紹了QR 二維碼中插入圖片實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Java Feign微服務(wù)接口調(diào)用方法詳細(xì)講解

    Java Feign微服務(wù)接口調(diào)用方法詳細(xì)講解

    現(xiàn)如今微服務(wù)架構(gòu)十分流行,而采用微服務(wù)構(gòu)建系統(tǒng)也會(huì)帶來更清晰的業(yè)務(wù)劃分和可擴(kuò)展性。java如果使用微服務(wù)就離不開springcloud,我這里是把服務(wù)注冊(cè)到nacos上,各個(gè)服務(wù)之間的調(diào)用使用feign
    2023-01-01
  • Java中通過繼承Thread類創(chuàng)建線程的步驟

    Java中通過繼承Thread類創(chuàng)建線程的步驟

    本文介紹了如何通過繼承Thread類創(chuàng)建線程,包括Thread類的定義、創(chuàng)建線程的步驟、優(yōu)缺點(diǎn)、使用場(chǎng)景和注意事項(xiàng),通過示例代碼展示了多線程下載文件的實(shí)現(xiàn),感興趣的朋友跟隨小編一起看看吧
    2025-02-02
  • java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲

    java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03

最新評(píng)論

伊通| 江孜县| 合肥市| 潞城市| 启东市| 乌拉特中旗| 扎囊县| 隆昌县| 通山县| 临潭县| 稷山县| 梅河口市| 长海县| 长治市| 永州市| 祁东县| 余姚市| 玛多县| 宁德市| 曲阜市| 虞城县| 牟定县| 古交市| 台州市| 丹棱县| 沐川县| 明光市| 许昌市| 荔浦县| 肃宁县| 黔西| 临江市| 敖汉旗| 扎鲁特旗| 台东县| 北安市| 司法| 当雄县| 新化县| 浮梁县| 景谷|