SpringBoot通过OSS实现文件上传和下载(包括本地文件的上传和下载)

最近项目中需要通过OSS来实现文件的上传和下载,特此记录,以便日后查阅。

首先你需要开通阿里云的OSS服务,注册得到相关的配置信息:endPoint、accessKeyId、accessKeySecret、bucketName。

1、引入依赖



    com.aliyun.oss
    aliyun-sdk-oss
    2.4.0


    commons-fileupload
    commons-fileupload
    1.3.1

2、properties配置

# 文件客户端类型
file.client.type=oss

# OSS
file.oss.endPoint=http://oss-cn-hangzhou.aliyuncs.com
file.oss.accessKeyId=去OSS控制台获取
file.oss.accessKeySecret=去OSS控制台获取
file.oss.bucketName=这个自己创建bucket时的命名
file.oss.rootDir=data

3、引导类配置

/**
 * 引导类
 *
 * @author zhangzhixiang
 * @date 2018/09/18 14:51:39
 */
@Configuration
public class BootstrapConsts {
    
    @Value("${file.client.type}")
    private String fileClientType;
       
    @Value("${file.oss.endPoint}")
    private String endPoint;

    @Value("${file.oss.accessKeyId}")
    private String accessKeyId;
    
    @Value("${file.oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${file.oss.bucketName}")
    private String bucketName;

    @Value("${file.oss.rootDir}")
    private String rootDir;
    
    /**
     * 文件客户端类型
     */
    public static String file_client_type;
    /**
     * OSS地址(不同服务器,地址不同)
     */
    public static String end_point;
    /**
     * OSS键id(去OSS控制台获取)
     */
    public static String access_key_id;
    /**
     * OSS秘钥(去OSS控制台获取)
     */
    public static String access_key_secret;
    /**
     * OSS桶名称(这个是自己创建bucket时候的命名)
     */
    public static String bucket_name;
    /**
     * OSS根目录
     */
    public static String root_dir;
    
    @PostConstruct
    private void initial() {
        file_client_type = fileClientType;
        end_point = endPoint;
        access_key_id = accessKeyId;
        access_key_secret = accessKeySecret;
        bucket_name = bucketName;
        root_dir = rootDir;
    }
}

4、文件工厂类

/**
 * 文件操作客户端生成类
 *
 * @author zhangzhixiang
 * @data 2018/09/14 11:56:43
 */
public class ClientFactory {

    private static final Logger logger = LoggerFactory.getLogger(ClientFactory.class);

    /**
     * 根据类型获取文件操作客户端
     *
     * @param type
     * @return
     */
    public static FileClient createClientByType(String type) {
        FileClient client = null;
        switch (type) {
            case "local":
                client = LocalClient.create();
                break;
            case "oss":
                client = OssClient.create();
                break;
            default:
                client = null;
                logger.info("the type of fileClient does not exist.please check the type.type={}", type);
                break;
        }
        return client;
    }
}

5、文件接口

/**
 * 本地文件操作类
 *
 * @author zhangzhixiang
 * @data 2018/09/14 11:56:43
 */
public interface FileClient {
    
    /**
     * 获取文件流
     *
     * @author zhangzhixiang
     * @date 2018/10/17 10:59:43
     * @param code
     * @return java.io.InputStream
     */
     InputStream getFileStream(String code);

    /**
     * 上传文件
     *
     * @param inputStream
     * @param filePath
     * @param ext
     * @author zhangzhixiang
     * @date 2018/10/17 10:59:43
     * @return boolean
     */
     String upload(InputStream inputStream, String filePath, String ext) throws Exception;

    /**
     * 下载文件
     *
     * @param response
     * @param filePath
     * @param name
     * @author zhangzhixiang
     * @date 2018/10/17 10:59:43
     * @return void
     */
     void download(HttpServletResponse response, String filePath, String name) throws Exception;

    /**
     * 删除文件
     *
     * @param dirPath
     * @author zhangzhixiang
     * @date 2018/10/17 10:59:43
     * @return void
     */
     void delete(String dirPath);

    /**
     * 获得url地址
     *
     * @param key
     * @author zhangzhixiang
     * @date 2018/10/17 10:59:43
     * @return java.lang.String
     */
     String getUrl(String key);

}

6、常量类定义

/**
 * @Description:简单常亮定义
 * @Author:zhangzhixiang
 * @CreateDate:2018/08/31 11:34:56
 * @Version:1.0
 */
public class SimpleConsts {
    
    public static final Integer INPUT_BUFFER_SIZE = 8192;

}

7、OSS客户端配置

/**
 * @Description:OSS客户端配置
 * @Author:zhangzhixiang
 * @CreateDate:2018/08/31 11:34:56
 * @Version:1.0
 */
public class OssClient implements FileClient {

    private static final Logger logger = LoggerFactory.getLogger(OssClient.class);

    private final char PATH_SEPARATOR = System.getProperty("file.separator").toCharArray()[0];

    private static OssClient ossClient;
    
    /**
     * @Description:获取aliOSS对象
     * @Author:zhangzhixiang
     */
    private OSSClient getClient() {
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(BootstrapConsts.end_point, BootstrapConsts.access_key_id, BootstrapConsts.access_key_secret);
        } catch(Exception e){
            logger.error("**********************OSSClient bean create error.**********************",e);
            ossClient = null;
        }
        return ossClient;
    }

    /**
     * @Description:创建OssClient
     * @Author:zhangzhixiang
     */
    public static FileClient create() {
        if(null == ossClient) {
            synchronized (logger) {
                if(null == ossClient) {
                    ossClient = new OssClient();    
                }
            }
        }
        return ossClient;
    }

    /**
     * @Description:根据code获取文件流
     * @Author:zhangzhixiang
     */
    @Override
    public InputStream getFileStream(String code) {
        OSSClient aliOssClient = getClient();
        OSSObject ossObject = aliOssClient.getObject(BootstrapConsts.bucket_name, BootstrapConsts.root_dir + PATH_SEPARATOR + code);
        return ossObject.getObjectContent();
    }

    /**
     * @Description:上传文件
     * @Author:zhangzhixiang
     */
    @Override
    public String upload(InputStream inputStream, String code, String ext) {
        OSSClient aliOssClient = getClient();
        code = UUIDUtils.getUUID();
        PutObjectResult putResult = aliOssClient.putObject(BootstrapConsts.bucket_name, BootstrapConsts.root_dir + PATH_SEPARATOR + code + ext, inputStream);
        aliOssClient.shutdown();
        return StringUtils.isNotEmpty(putResult.getETag()) ? BootstrapConstss.root_dir + PATH_SEPARATOR + code + ext : null;
    }

    /**
     * @Description:下载文件
     * @Author:zhangzhixiang
     */
    @Override
    public void download(HttpServletResponse response, String code, String name) {
        OSSClient aliOssClient = getClient();
        OSSObject ossObject = aliOssClient.getObject(BootstrapConsts.bucket_name, BootstrapConsts.root_dir + PATH_SEPARATOR + code);
        try (InputStream fis = ossObject.getObjectContent(); OutputStream fos = response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + new String(name.getBytes("UTF-8"), "ISO-8859-1"));
            int bytesRead = 0;
            byte[] buffer = new byte[SimpleConsts.INPUT_BUFFER_SIZE];
            while((bytesRead = fis.read(buffer, 0, SimpleConsts.INPUT_BUFFER_SIZE)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush();
        } catch (Exception e){
            logger.error("**********************OssClient-->download throw Exception.name:{},code:{}**********************", name, code, e);
        }
        aliOssClient.shutdown();
    }

    /**
     * @Description:删除文件
     * @Author:zhangzhixiang
     */
    @Override
    public void delete(String code) {
        OSSClient aliOssClient = getClient();
        boolean flag = aliOssClient.doesObjectExist(BootstrapConsts.bucket_name, code);
        if(false == flag) {
            logger.info("**********************The object represented by key:{} does not exist in bucket:{}.**********************", code, BootstrapConsts.bucket_name);
        }
        aliOssClient.deleteObject(BootstrapConsts.bucket_name, code);
    }

    /**
     * @Description:获取文件地址
     * @Author:zhangzhixiang
     */
    @Override
    public String getUrl(String code) {
        OSSClient aliOssClient = getClient();
        //设置URL过期时间为10年
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        //生成URL
        URL url = aliOssClient.generatePresignedUrl(BootstrapConsts.bucket_name, code, expiration);
        if(url != null) {
            return url.toString();
        }
        return null;
    }

    /**
     * @Description:生成文件名
     * @Author:zhangzhixiang
     */
    private String createFileName(String ext) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return simpleDateFormat .format(new Date()) + (int)(Math.random() * 900 + 100) + ext;
    }
    
    /**
     * @Description:生成OSS文件唯一标识
     * @Author:zhangzhixiang
     */
    private String generateKey(String filename) {
        StringBuffer buffer = new StringBuffer();
        try {
            buffer.append(filename);
            buffer.append(Math.random());
            return EncodeUtil.encodeFromMD5ToBase64(buffer.toString());
        } catch(NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

8、UUIDUtils类

/**
 * @author zxzhang on 2020/8/1
 */
public class UUIDUtils {

    /**
     * 32位默认长度的uuid
     *
     * @param
     * @return java.lang.String
     * @author zxzhang
     * @date 2020/8/1
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 获取指定长度uuid
     *
     * @param len
     * @return java.lang.String
     * @author zxzhang
     * @date 2020/8/1
     */
    public static String getUUID(int len) {
        if (0 >= len) {
            return null;
        }

        String uuid = getUUID();
        System.out.println(uuid);
        StringBuffer str = new StringBuffer();

        for (int i = 0; i < len; i++) {
            str.append(uuid.charAt(i));
        }

        return str.toString();
    }
}

9、本地客户端配置

/**
 * @Description:本地客户端配置
 * @Author:zhangzhixiang
 * @CreateDate:2018/10/18 11:47:36
 * @Version:1.0
 */
public class LocalClient implements FileClient {

    private static final Logger logger = LoggerFactory.getLogger(LocalClient.class);

    private final char PATH_SEPARATOR = System.getProperty("file.separator").toCharArray()[0];

    private static LocalClient client;

    private LocalClient() {}

    /**
     * @Description:创建客户端
     * @Author:zhangzhixiang
     */
    public static FileClient create() {
        if(null == client) {
            synchronized (logger) {
                if(null == client) {
                    if(null == client) {
                        client = new LocalClient();
                    }
                }
            }
        }
        return client;
    }

    /**
     * @Description:获得文件流
     * @Author:zhangzhixiang
     */
    @Override
    public InputStream getFileStream(String code) {
        return null;
    }

    /**
     * @Description:上传文件
     * @Author:zhangzhixiang
     */
    @Override
    public String upload(InputStream inputStream, String filePath, String ext) throws Exception {
        File dir = new File(filePath);
        FileOutputStream out = null;
        try {
            if(!dir.exists()) {
                dir.mkdirs();
            }
            filePath = filePath + PATH_SEPARATOR + createFileName(ext);
            File file = new File(filePath);
            out = new FileOutputStream(file);
            int b = 0;
            byte[] buffer = new byte[512];
            while ((b = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, b);
            }
            out.flush();
            return filePath;
        } catch (IOException e) {
            logger.info("**************************LocalClient-->upload throw Exception.filePath:{}**************************", filePath);
            throw e;
        } finally {
            if(out != null) {
                out.close();
            }
            if(inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * @Description:下载文件
     * @Author:zhangzhixiang
     */
    @Override
    public void download(HttpServletResponse response, String filePath, String name) throws Exception {
        response.setContentType("application/octet-stream; charset=UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + new String(name.getBytes("UTF-8"), "ISO-8859-1"));
        File file = new File(filePath + PATH_SEPARATOR + name);
        try (InputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); OutputStream fos = response.getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            int bytesRead = 0;
            byte[] buffer = new byte[SimpleConsts.INPUT_BUFFER_SIZE];
            while ((bytesRead = bis.read(buffer, 0, SimpleConsts.INPUT_BUFFER_SIZE)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush();
        } catch(Exception e) {
            logger.info("**************************LocalClient-->download throw Exception.filePath:{}**************************", filePath);
        }
    }

    /**
     * @Description:删除文件
     * @Author:zhangzhixiang
     */
    @Override
    public void delete(String dirPath) {
        File dir = new File(dirPath);
        if (dir.exists()) {
            if(dir.isFile()) {
                dir.delete();
            } else {
                File[] tmp = dir.listFiles();
                for(int i = 0; i < tmp.length; i++) {
                    if (tmp[i].isDirectory()) {
                        delete(dirPath + PATH_SEPARATOR + tmp[i].getName());
                    } else {
                        tmp[i].delete();
                    }
                }
                dir.delete();
            }
        }
    }

    /**
     * @Description:获取文件地址
     * @Author:zhangzhixiang
     */
    @Override
    public String getUrl(String key) {
        return null;
    }

    /**
     * @Description:生成文件名
     * @Author:zhangzhixiang
     */
    private String createFileName(String ext) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return simpleDateFormat.format(new Date()) + (int) (Math.random() * 900 + 100) + ext;
    }
}

10、controller层

/**
 * @Description:文件接口-controller
 * @Author:zhangzhixiang
 * @CreateDate:2018/10/18 11:47:36
 * @Version:1.0
 */
@RestController
@RequestMapping("/api/ops/file")
public class FileController extends ExceptionHandlerAdvice {
    
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * @Description:文件上传
     * @Author:zhangzhixiang
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ResponseResult upload(@RequestParam("file") MultipartFile file) throws Exception {
        Map map = new HashMap<>(64);
        FileClient fileClient = ClientFactory.createClientByType(BootstrapConsts.file_client_type);
        String ext = this.getExtName(file.getOriginalFilename());
        String code = fileClient.upload(file.getInputStream(), "/", ext);
        String url = fileClient.getUrl(code);
        map.put("code", code.substring(code.lastIndexOf("/") + 1).substring(code.lastIndexOf("\\") + 1));
        map.put("url", url);
        return new ResponseResult().setSuccess(true).setData().setCode(ResultCode.SUCCESS.getCode());
    }

    /**
     * @Description:文件下载
     * @Author:zhangzhixiang
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public ResponseResult download(@RequestParam("code") String code, @RequestParam("name") String name, HttpServletResponse response) throws Exception {
        FileClient fileClient = ClientFactory.createClientByType(BootstrapConsts.file_client_type);
        fileClient.download(response, code, name);
        return new ResponseResult().setSuccess(true).setMessage(ResultCode.SUCCESS.getMessage()).setCode(ResultCode.SUCCESS.getCode());
    }

    /**
     * 获取文件扩展名
     * @return
     */
    public static String getExtName(String filename) {
        int index = filename.lastIndexOf(".");

        if (index == -1) {
            return null;
        }
        String result = filename.substring(index);
        return result;
    }
}

全篇文章完全纯手打,如果觉得对您有帮助,记得加关注给好评哟~~

你可能感兴趣的:(OSS)