Springboot 迁移及上传文件至阿里云OSS

栏目: Java · 发布时间: 6年前

内容简介:本文介绍GitClub小程序后端的服务器文件的迁移以及更新图片上传至阿里云OSS存储服务器,如果不了解GitClub小程序的朋友可以看下我的上篇文章因为之前我们的图片上传至项目目录中的指定路径如:

本文介绍GitClub小程序后端的服务器文件的迁移以及更新图片上传至阿里云OSS存储服务器,如果不了解GitClub小程序的朋友可以看下我的上篇文章 关于Android开源库分享平台,(GitClub)微信小程序的开发体验 ,在此特别纠正下,当前版本暂时只有Android的开源库分享,后续会增加 Java 、iOS、前端等不同语言的分类,感兴趣的可以去关注下我们的小程序,源码地址: GitClub 。铺垫结束,请使用扫描这个二维码登陆GitClub小程序参观。

Springboot 迁移及上传文件至阿里云OSS

一、导入依赖包,在pox.xml中加入

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.8.3</version>
</dependency>
复制代码

二、配置OSS的参数,创建类OSSConfig

1、添加oss.properties配置文件,内容如下:
#阿里云OSS配置
#原服务器地址
bucketUrl = https://bucketName.oss-cn-shenzhen.aliyuncs.com
#自定义解析后服务器地址
baseUrl = https://xxx.502tech.com
#可以选择其他的地址
endpoint = https://oss-cn-qingdao.aliyuncs.com
#已经在控制台创建的bucket
bucketName = bucketName
#你上传文件的保存路径,如果bucket中不存在则创建(其实原理并不是文件夹,只是文件名,详情请先阅读官方文档)
picLocation = GitClub/image/
#相应的id和key值,请填写你具体的值,这里不方便展示我自己的。
accessKeyId = 阿里云OSS的accessKeyId
accessKeySecret = 阿里云OSS的accessKeySecret

2、创建类OSSConfig
public class OSSConfig {

    private  String bucketUrl;  		//原图片服务器地址
    private  String baseUrl;  		//自定义解析后的图片服务器地址
    private  String endpoint;  		//连接区域地址
    private  String accessKeyId;  	//连接keyId
    private  String accessKeySecret;    //连接秘钥
    private  String bucketName;  	//需要存储的bucketName
    private  String picLocation;  	//图片保存路径

    public OSSConfig() {
        try {
            this.bucketUrl = SystemConfig.getConfigResource("bucketUrl");
            this.baseUrl = SystemConfig.getConfigResource("baseUrl");
            this.endpoint = SystemConfig.getConfigResource("endpoint");
            this.bucketName = SystemConfig.getConfigResource("bucketName");
            this.picLocation = SystemConfig.getConfigResource("picLocation");
            this.accessKeyId = SystemConfig.getConfigResource("accessKeyId");
            this.accessKeySecret = SystemConfig.getConfigResource("accessKeySecret");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    ...
    省略get、set方法
复制代码

三、创建OSS工具类OSSUploadUtil

private static OSSConfig config = null;

    /**
     *
     * @MethodName: uploadFile
     * @Description: OSS单文件上传
     * @param file
     * @param fileType 文件后缀
     * @return String 文件地址
     */
    public static String uploadFile(File file,String fileType){
        config = config == null ? new OSSConfig():config;
        //通过UUID生成文件名
        String fileName = config.getPicLocation()
                +UUID.randomUUID().toString().toUpperCase()
                .replace("-", "")
                +"."+fileType;
        return putFile(file,fileType,fileName);
    }

    /**
     *
     * @MethodName: updateFile
     * @Description: 更新文件:只更新内容,不更新文件名和文件地址。
     * 		(因为地址没变,可能存在浏览器原数据缓存,不能及时加载新数据,例如图片更新,请注意)
     * @param file
     * @param fileType
     * @param oldUrl
     * @return String
     */
    public static String updateFile(File file,String fileType,String oldUrl){
        String fileName = getFileName(oldUrl);
        if(fileName==null) return null;
        return putFile(file,fileType,fileName);
    }

    /**
     *
     * @MethodName: replaceFile
     * @Description: 替换文件:删除原文件并上传新文件,文件名和地址同时替换
     * 		解决原数据缓存问题,只要更新了地址,就能重新加载数据)
     * @param file
     * @param fileType 文件后缀
     * @param oldUrl 需要删除的文件地址
     * @return String 文件地址
     */
    public static String replaceFile(File file,String fileType,String oldUrl){
        boolean flag = deleteFile(oldUrl);		//先删除原文件
        if(!flag){
            //更改文件的过期时间,让他到期自动删除。
        }
        return uploadFile(file, fileType);
    }

    /**
     *
     * @MethodName: deleteFile
     * @Description: 单文件删除
     * @param fileUrl 需要删除的文件url
     * @return boolean 是否删除成功
     */
    public static boolean deleteFile(String fileUrl){
        config = config == null ? new OSSConfig():config;

        String bucketName = OSSUploadUtil.getBucketName(fileUrl);		//根据url获取bucketName
        String fileName = OSSUploadUtil.getFileName(fileUrl);			//根据url获取fileName
        if(bucketName==null||fileName==null) return false;
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret());
            GenericRequest request = new DeleteObjectsRequest(bucketName).withKey(fileName);
            ossClient.deleteObject(request);
        } catch (Exception oe) {
            oe.printStackTrace();
            return false;
        } finally {
            ossClient.shutdown();
        }
        return true;
    }

    /**
     *
     * @MethodName: batchDeleteFiles
     * @Description: 批量文件删除(较快):适用于相同endPoint和BucketName
     * @param fileUrls 需要删除的文件url集合
     * @return int 成功删除的个数
     */
    public static int deleteFile(List<String> fileUrls){
        int deleteCount = 0;	//成功删除的个数
        String bucketName = OSSUploadUtil.getBucketName(fileUrls.get(0));		//根据url获取bucketName
        List<String> fileNames = OSSUploadUtil.getFileName(fileUrls);			//根据url获取fileName
        if(bucketName==null||fileNames.size()<=0) return 0;
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret());
            DeleteObjectsRequest request = new DeleteObjectsRequest(bucketName).withKeys(fileNames);
            DeleteObjectsResult result = ossClient.deleteObjects(request);
            deleteCount = result.getDeletedObjects().size();
        } catch (OSSException oe) {
            oe.printStackTrace();
            throw new RuntimeException("OSS服务异常:", oe);
        } catch (ClientException ce) {
            ce.printStackTrace();
            throw new RuntimeException("OSS客户端异常:", ce);
        } finally {
            ossClient.shutdown();
        }
        return deleteCount;

    }

    /**
     *
     * @MethodName: batchDeleteFiles
     * @Description: 批量文件删除(较慢):适用于不同endPoint和BucketName
     * @param fileUrls 需要删除的文件url集合
     * @return int 成功删除的个数
     */
    public static int deleteFiles(List<String> fileUrls){
        int count = 0;
        for (String url : fileUrls) {
            if(deleteFile(url)){
                count++;
            }
        }
        return count;
    }

    /**
     *
     * @MethodName: putFile
     * @Description: 上传文件
     * @param file
     * @param fileType
     * @param fileName
     * @return String
     */
    private static String putFile(File file, String fileType, String fileName){
        config = config==null?new OSSConfig():config;
        String url = null;		//默认null
        OSSClient ossClient = null;
        try {
            ossClient = new OSSClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret());
            InputStream input = new FileInputStream(file);
            ObjectMetadata meta = new ObjectMetadata();				// 创建上传Object的Metadata
            meta.setContentType(OSSUploadUtil.contentType(fileType));		// 设置上传内容类型
            meta.setCacheControl("no-cache");					// 被下载时网页的缓存行为
            PutObjectRequest request = new PutObjectRequest(config.getBucketName(), fileName,input,meta);			//创建上传请求
            ossClient.putObject(request);
            Date expiration = new Date(new Date().getTime() + 3600L * 1000 * 24 * 365 * 10); // 设置URL过期时间为10年  3600L* 1000*24*365*10
            //上传成功再返回的文件路径
            url = ossClient.generatePresignedUrl(config.getBucketName(), fileName, expiration)
                                                .toString()
                                                .replaceFirst(config.getBucketUrl(), config.getBaseUrl());
        } catch (OSSException | FileNotFoundException | ClientException oe) {
            oe.printStackTrace();
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return url;
    }

    /**
     *
     * @MethodName: contentType
     * @Description: 获取文件类型
     * @param fileType
     * @return String
     */
    private static String contentType(String fileType){
        fileType = fileType.toLowerCase();
        String contentType = "";
        switch (fileType) {
            case "bmp":	contentType = "image/bmp";
                break;
            case "gif":	contentType = "image/gif";
                break;
            case "png":
            case "jpeg":
            case "jpg":	contentType = "image/jpeg";
                break;
            case "html":contentType = "text/html";
                break;
            case "txt":	contentType = "text/plain";
                break;
            case "vsd":	contentType = "application/vnd.visio";
                break;
            case "ppt":
            case "pptx":contentType = "application/vnd.ms-powerpoint";
                break;
            case "doc":
            case "docx":contentType = "application/msword";
                break;
            case "xml":contentType = "text/xml";
                break;
            case "mp4":contentType = "video/mp4";
                break;
            default: contentType = "application/octet-stream";
                break;
        }
        return contentType;
    }

    /**
     *
     * @MethodName: getBucketName
     * @Description: 根据url获取bucketName
     * @param fileUrl 文件url
     * @return String bucketName
     */
    private static String getBucketName(String fileUrl){
        String http = "http://";
        String https = "https://";
        int httpIndex = fileUrl.indexOf(http);
        int httpsIndex = fileUrl.indexOf(https);
        int startIndex  = 0;
        if(httpIndex==-1){
            if(httpsIndex==-1){
                return null;
            }else{
                startIndex = httpsIndex+https.length();
            }
        }else{
            startIndex = httpIndex+http.length();
        }
        int endIndex = fileUrl.indexOf(".oss-");
        return fileUrl.substring(startIndex, endIndex);
    }

    /**
     *
     * @MethodName: getFileName
     * @Description: 根据url获取fileName
     * @param fileUrl 文件url
     * @return String fileName
     */
    private static String getFileName(String fileUrl){
        String str = "aliyuncs.com/";
        int beginIndex = fileUrl.indexOf(str);
        if(beginIndex==-1) return null;
        return fileUrl.substring(beginIndex+str.length());
    }

    /**
     *
     * @MethodName: getFileName
     * @Description: 根据url获取fileNames集合
     * @param fileUrls 文件url
     * @return List<String>  fileName集合
     */
    private static List<String> getFileName(List<String> fileUrls){
        List<String> names = new ArrayList<>();
        for (String url : fileUrls) {
            names.add(getFileName(url));
        }
        return names;
    }

}
复制代码

四、测试

//把之前上传到项目特定目录下的逻辑修改成上传至OSS
@PostMapping("/uploadArticleImg")
    public Result<Map<String, String>> uploadArticleImg(@RequestParam(value = "article_img") MultipartFile file) {
        if (file == null || file.isEmpty() || file.getSize() == 0) {
            return ResultUtils.error(ResultCode.UPLOAD_FILE_EMPTY);
        }
        if (file.getSize() > 10 * 1024 * 1024) {
            return ResultUtils.error(ResultCode.UPLOAD_FILE_LIMIT);
        }
        Map<String, String> map = new HashMap<>();
        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
        //OSS单文件上传,返回上传成功后的oss存储服务器中的url
        String fileName = OSSUploadUtil.uploadFile(FileUtils.multi2File(file), fileType);
        map.put(file.getName(), fileName);
        return ResultUtils.ok(map);
    }
复制代码

五、如何把数据库中把之前已经上传的文件URL更新成OSS返回的URL

@PostMapping("/trasform2OSS")
    public Result<Boolean> trasformImg2OSS(){
        File path = null;
        try {
            path = new File(ResourceUtils.getURL("classpath:").getPath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (!path.exists()) path = new File("");
        System.out.println("path:" + path.getAbsolutePath());
        //如果上传目录为/static/images/upload/,则可以如下获取:
        File upload = new File(path.getAbsolutePath(), "static/images/upload/");
        if (!upload.exists()) upload.mkdirs();
        System.out.println("upload url:" + upload.getAbsolutePath());
        File[] files = upload.listFiles();

        //更新图片的url到oss  并把最新oss的图片地址保存到数据库
        List<Article> articles = articleRepository.findAll();
        articles.forEach(article -> {
            if (null != article){
                for (File file : files){
                    if(null != file){
                        if(null == article.getImg_url() || null == file.getName()){
                            continue;
                        }
                        if(article.getImg_url().contains(file.getName())){
                            //上传到oss
                            String fileType = file.getName().substring(file.getName().lastIndexOf(".")+1);
                            String url = OSSUploadUtil.uploadFile(file, fileType);
                            logger.info("上传到oss地址:"+url);
                            //更新到服务器
                            article.setImg_url(url);
                            articleRepository.saveAndFlush(article);
                            //更新数据到引擎
                            articleSearchRepository.save(new ESArticle(article));
                        }
                    }
                }
            }
        });
        return ResultUtils.ok(true);
    }
复制代码

六、阿里云OSS管理配置的一些坑

因为之前我们的图片上传至项目目录中的指定路径如: 502tech.com/geekdaily/x… 现在需要全部替换成如: xxx.502tech.com/123.png 格式,注意:这里xxx.502tech.com是我们的二级域名,上传文件至OSS之后默认会返回如: bucketName.oss-cn-shenzhen.aliyuncs.com/123.png 格式。需要我们手动在阿里云OSS域名管理中去绑定域名,如果想要使用https,则需要申请SSL证书,这里你可以申请一个免费的,可以自行百度,大概15分钟会申请成功,然后需要在OSS的域名管理中添加SSL证书,这里切记:下载nginx版本的证书,然后复制粘贴对应的公钥和私钥。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beautiful Code

Beautiful Code

Greg Wilson、Andy Oram / O'Reilly Media / 2007-7-6 / GBP 35.99

In this unique work, leading computer scientists discuss how they found unusual, carefully designed solutions to difficult problems. This book lets the reader look over the shoulder of major coding an......一起来看看 《Beautiful Code》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具