因为工作需要,最近在网上查的很多有关此方面的资料,最后完成了此功能,写下来作为笔记。

前期准备:

1.获取到亚马逊云服务的ACCESS_KEY,SECRET_KEY,BUCKET_NAME(桶名),REGION(云服务所属的地区),PATH(存储在云服务的路径)。

2.和前端规定好要传的图片的格式,因为我这边规定好的格式是bs64,所以要先转换成


MultipartFile在进行上传。并且平常的一般上传都是先存储在本地,然后在上传。因为我们这个需求不需要存储在本地,所以我们这边是前端传过来图片的bs64,然后直接进行上传,不存储在本地.


代码阶段:

controller层:

/**
     * 图片上传
     */
    @ApiOperation("图片上传")
    @RequestMapping(value = "uploading", method = RequestMethod.POST)
    public RestResponse uploading(@RequestBody @Valid GatewayRequest<PutRequest> rq) {
        String apiName = "图片上传";
        KycPutRequest content = rq.getContent();
        RestResponse restResponse = null;
        try {
            restResponse = ManageService.upload(content);
        }catch (Exception e){
            log.error("[ERROR|{}][Controller|put] 异常[{}]", apiName, e);
            restResponse=RestResponse.error();
        }
       return restResponse;
    }

serviceImpl层:

@Override
    public RestResponse upload(KycPutRequest content) throws Exception {
        String bs64 = "data:image/png;base64," + content.getBase64Data();//base64Data就是接受前端的bs64的参数,string类型的。
        MultipartFile multipartFile = BASE64DecodedMultipartFile.base64ToMultipart(bs64);
        log.info("multipartfile:"+multipartFile);
        if (multipartFile==null){
            return RestResponse.error("转化失败");
        }
        String downloadFile = FileUtils.uploadFile(multipartFile);
        log.info("url:"+downloadFile);
        return RestResponse.success(downloadFile);
    }

bs64转MultipartFile格式:

package com.gigaiot.bc.core.utils;

import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
 
/**
 * @ClassName BASE64DecodedMultipartFile
 * @Description TODO
 * @Author Uncle
 * @Date 2021/05/25 17:17
 * @Version 1.0
 */
public class BASE64DecodedMultipartFile implements MultipartFile {
 
    private final byte[] imgContent;
    private final String header;
 
    public BASE64DecodedMultipartFile(byte[] imgContent, String header) {
        this.imgContent = imgContent;
        this.header = header.split(";")[0];
    }
 
    @Override
    public String getName() {
        // TODO - implementation depends on your requirements
        return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
    }
 
    @Override
    public String getOriginalFilename() {
        // TODO - implementation depends on your requirements
        return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
    }
 
    @Override
    public String getContentType() {
        // TODO - implementation depends on your requirements
        return header.split(":")[1];
    }
 
    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }
 
    @Override
    public long getSize() {
        return imgContent.length;
    }
 
    @Override
    public byte[] getBytes() throws IOException {
        return imgContent;
    }
 
    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(imgContent);
    }
 
    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        new FileOutputStream(dest).write(imgContent);
    }
 
    /**
     * base64转MultipartFile文件
     *
     * @param base64
     * @return
     */
    public static MultipartFile base64ToMultipart(String base64) {
        try {
            String[] baseStrs = base64.split(",");
 
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            b = decoder.decodeBuffer(baseStrs[1]);
 
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
 
            return new BASE64DecodedMultipartFile(b, baseStrs[0]);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
 
 
    /**
     * base64转MultipartFile文件
     *
     * @param base64
     * @return
     */
    public static MultipartFile base64ToMultipartOnt(String base64) {
        try {
 
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            b = decoder.decodeBuffer(base64);
 
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
 
            return new BASE64DecodedMultipartFile(b, base64);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 本地图片转换成base64字符串
     *
     * @param imgFile 图片本地路径
     * @return
     * @author uncle
     * @dateTime 2018-02-23 14:40:46
     */
    public static String ImageToBase64ByLocal(String imgFile) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
 
 
        InputStream in = null;
        byte[] data = null;
 
        // 读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
 
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
 
        return encoder.encode(data);// 返回Base64编码过的字节数组字符串
    }
 
 
    /**
     * 在线图片转换成base64字符串
     *
     * @param imgURL 图片线上路径
     * @return
     * @author uncle
     * @dateTime 2018-02-23 14:43:18
     */
    public static String ImageToBase64ByOnline(String imgURL) {
        ByteArrayOutputStream data = getByteArrayOutputStream(imgURL);
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data.toByteArray());
    }
 
    public static byte[] ImageToByteByOnline(String imgURL) {
        ByteArrayOutputStream data = getByteArrayOutputStream(imgURL);
        return data.toByteArray();
    }
 
    private static ByteArrayOutputStream getByteArrayOutputStream(String imgURL) {
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            // 创建URL
            URL url = new URL(imgURL);
            byte[] by = new byte[1024];
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            InputStream is = conn.getInputStream();
            // 将内容读取内存中
            int len = -1;
            while ((len = is.read(by)) != -1) {
                data.write(by, 0, len);
            }
            // 关闭流
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
 
 
    /**
     * base64字符串转换成图片
     *
     * @param imgStr      base64字符串
     * @param imgFilePath 图片存放路径
     * @return
     * @author uncle
     * @dateTime 2018-02-23 14:42:17
     */
    public static boolean Base64ToImage(String imgStr, String imgFilePath) { // 对字节数组字符串进行Base64解码并生成图片
 
        if (imgStr == null) {
            // 图像数据为空
            return false;
        }
 
 
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            // Base64解码
            byte[] b = decoder.decodeBuffer(imgStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
 
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(b);
            out.flush();
            out.close();
 
            return true;
        } catch (Exception e) {
            return false;
        }
 
    }
 
    /**
     * 功能描述 :MultipartFile转file对象
     *
     * @param
     * @return
     * @author uncle
     * @date 2019/5/10 18:30
     */
    public static File MultipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 用当前时间作为文件名,防止生成的临时文件重复
        try {
            File file = File.createTempFile(System.currentTimeMillis() + "", prefix);
 
            multiFile.transferTo(file);
 
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

aws图片上传工具类:

package com.gigaiot.bc.core.utils;


import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.sun.jna.platform.win32.WinNT;
import org.aspectj.weaver.ast.Var;
import org.springframework.web.multipart.MultipartFile;

import javax.xml.bind.SchemaOutputResolver;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileUtils {
    //密匙
    static final String ACCESS_KEY ="***";
 
    static final String SECRET_KEY ="*****";

    //储存桶的名称
    static final String BUCKET_NAME ="****";

    //所属地区
    static final String REGION = "ap-east-1";


    //储存路径,不同太在意我的,填你自己想要储存的路径
    static final String PATH="/test";
 
    static final BasicAWSCredentials awsCreds = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
 
    static final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
            .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
            //设置服务器所属地区
            .withRegion(Regions.AP_SOUTHEAST_1)
            .build();
 
    /**
     * 上传到文件返回一个文件储存后的路径
     * @param multipartFile
     * @return
     * @throws Exception
     */
    public static String uploadFile(MultipartFile multipartFile)  {
        if (multipartFile.isEmpty()) {
            return "文件为空";
        }
        Date date = new Date();
        SimpleDateFormat formatter_yyyy = new SimpleDateFormat("yyyy");
        SimpleDateFormat formatter_MM = new SimpleDateFormat("MM");
        //在随机名前加上年月
        String s3FilePath =PATH + "/" +formatter_yyyy.format(date) + "/" + formatter_MM.format(date) + "/" + multipartFile.getOriginalFilename();
        System.out.println("照片:"+s3FilePath);
        ObjectMetadata metadata  = new ObjectMetadata();
        metadata.setContentType(multipartFile.getContentType());
        metadata.setContentLength(multipartFile.getSize());
        try {
            //开始上传文件
            //1.不支持公网访问
            //s3.putObject(BUCKET_NAME, s3FilePath, multipartFile.getInputStream(), metadata)
            //2.支付公网访问
            PutObjectResult putObjectResult=s3.putObject(new PutObjectRequest(BUCKET_NAME, s3FilePath, multipartFile.getInputStream(), metadata)
                    .withCannedAcl(CannedAccessControlList.PublicRead));
            putObjectResult.getContentMd5();
            System.err.println("上传完成__文件位置为" + putObjectResult);
            GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, s3FilePath);
            URL url = s3.generatePresignedUrl(httpRequest);
            return url.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回文件位置
        return null;
    }
 
    /**
     * 用过文件路径获取文件下载地址
     * @param path
     * @return
     */
    public static String downloadFile(String path){
        try {
            GeneratePresignedUrlRequest httpRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, path);
            return s3.generatePresignedUrl(httpRequest).toString()+path;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "获取失败";
    }
 
}

所需要的架包:

<dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.34</version>
        </dependency>

注意:

1.发现的问题是:如果部署的aws地区为香港,按文档的指示应该REGION为ap-east-1。但是我在

python上传亚马逊云图片 亚马逊图片上传链接_python上传亚马逊云图片

 并没有发现香港地区的区域代码,所以刚刚开始的时候以为是aws的版本号问题,在更换几个版本号之后,还是无效,所以就采取了这种方法

python上传亚马逊云图片 亚马逊图片上传链接_字符串_02

 这样代码是没有报错,但是运行后,日志显示,系统总将这个地区识别为us-east-2地区,所以总数失败,最后找到相关的工作人员,更新到了最新的aws架包,v2的架包还是无效,没有找到。所以迫于无奈的情况下,运维将服务器部署到了新加坡节点,立刻就成功了,这个问题目前还是没有解决,为什么会出现这种情况,希望哪位大神可以告诉一下。