上周使用 base64 上传图片到OSS中的时候,发现保存的图片出现显示马赛克和图片破损打不开的情况。找了很久也没有出现问题,今天在找答案的时候,偶然间发现有个博主分享的内容完美的解决了我的问题(这里特别感谢这位博主的分享),所以特此记录一下,希望能够帮助遇到同样问题却又苦苦挣扎的朋友们。

关于 base64编码 保存的图片无法正常显示的问题,需要注意两点:

1)上传使用的 base64编码 只需要 “data:image/png;base64,”(这个是指图片的格式,也有可能是“data:image/jpeg;base64,”等)之后的字符串,所以一定要去掉这个前缀。

备注:截取的时候可以使用 base64字符串.substring(base64字符串.indexOf(",") + 1) 方法;

2)如果第一点已经确认写的没问题,但是图片仍然显示有问题(我就是这个问题),那么可以继续往下看:

Postman/Ajax (我是使用Postman的时候出现的问题) 在传 base64编码 的时候,会把 base64编码 中的 "+" 号换成空格,所以需要先将base64中的空格转换回来,再进行保存操作!

 

下面是使用 base64编码 上传的工具类:

public static String getBase64ToImg(String userPhoto,String userId){

        Date date = new Date();
        SimpleDateFormat sft = new SimpleDateFormat("yyyy-MM-dd");

        String newUserPhoto = null;

        // 判断base64编码是否为空
        if(StringUtils.notNull(userPhoto)){	// base64编码不为空

            // 1)截取获取到的base64编码,去掉前缀"data:image/png;base64," || "data:image/jpeg;base64,",只取base64编码
            // 2)需要将 base64编码 中的空格转换成 + 号
            userPhoto = userPhoto.substring(userPhoto.indexOf(",") + 1).replaceAll(" ", "+");

            try {
                
                newUserPhoto = "images/" + sft.format(date).toString() + "/" + userId + ".png"; 

                //Base64解码
                BASE64Decoder decoder = new BASE64Decoder();
                byte[] photoBase64 = decoder.decodeBuffer(userPhoto);
                for(int i=0;i<photoBase64.length;++i)
                {
                    if(photoBase64[i]<0)
                    {//调整异常数据
                        photoBase64[i]+=256;
                    }
                }

                /* 保存到本地 如果要保存到OSS中,这个块可以不用写 begin*/
                // 创建当前日期的文件件
                File file = new File("images/" + sft.format(date).toString() + "/");
                file.mkdirs();

                newUserPhoto = "images/" + sft.format(date).toString() + "/" + userId +".png"; //新生成的图片
                OutputStream out = new FileOutputStream(newUserPhoto);
                out.write(photoBase64);
                out.flush();
                out.close();
                /* 保存到本地 end*/


                /* 上传至OSS 如果需要将图片上传至OSS,只需要在 Base64解码 之后,直接调用OSS的SDK即可,不需要再保存到本地  begin*/
                // Endpoint以杭州为例,其它Region请按实际情况填写。
                String endpoint = "http://oss-cn-beijing.aliyuncs.com";
                // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建。
                String accessKeyId = "xxxxxxx";
                String accessKeySecret = "xxxxxxxx";
                String bucketName = "images";

                // 创建OSSClient实例。
                OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret);

                // 上传Byte数组。
                ossClient.putObject(bucketName, newUserPhoto, new ByteArrayInputStream(photoBase64));

                // 关闭OSSClient。
                ossClient.shutdown();
                /* 上传至OSS 如果需要将图片上传至OSS,只需要在 Base64解码 之后,直接调用OSS的SDK即可,不需要再保存到本地  end*/

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return newUserPhoto;
    }