public class PutObjectProgressListener implements ProgressListener {
        private long bytesWritten = 0;
        private long totalBytes = -1;
        private boolean succeed = false;
        @Override
        public void progressChanged(ProgressEvent progressEvent) {
            long bytes = progressEvent.getBytes();
            ProgressEventType eventType = progressEvent.getEventType();
            switch (eventType) {
            case TRANSFER_STARTED_EVENT:
                System.out.println("Start to upload......");
                break;
            case REQUEST_CONTENT_LENGTH_EVENT:
                this.totalBytes = bytes;
                System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");
                break;
            case REQUEST_BYTE_TRANSFER_EVENT:
                this.bytesWritten += bytes;
                if (this.totalBytes != -1) {
                    int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
                    System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
                } else {
                    System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
                }
                break;
            case TRANSFER_COMPLETED_EVENT:
                this.succeed = true;
                System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
                break;
            case TRANSFER_FAILED_EVENT:
                System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
                break;
            default:
                break;
            }
        }
        public boolean isSucceed() {
            return succeed;
        }
        public static void main(String[] args) {
            // Endpoint以杭州为例,其它Region请按实际情况填写。
            String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
            // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
            String accessKeyId = "<yourAccessKeyId>";
            String accessKeySecret = "<yourAccessKeySecret>";
            String bucketName = "<yourBucketName>";
            String objectName = "<yourObjectName>";
            // 创建OSSClient实例。
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            try {
                // 带进度条的上传。
                ossClient.putObject(new PutObjectRequest(bucketName, objectName, new FileInputStream("<yourLocalFile>")).
                        <PutObjectRequest>withProgressListener(new PutObjectProgressListener()));
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 关闭OSSClient。
            ossClient.shutdown();
        }
    }

引用到spring boot 中的项目中之后的代码:

1.文件上传及监听器:

import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSSClient;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.event.ProgressEvent;
    import com.aliyun.oss.event.ProgressEventType;
    import com.aliyun.oss.event.ProgressListener;
    import com.aliyun.oss.model.PutObjectRequest;
    import com.aliyun.oss.model.PutObjectResult;
    import com.google.common.collect.Lists;
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
     
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.net.URL;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
     
    /**
     *  2018/7/25.
     */
    public class OssUploadUtil {
        private static Logger logger = LoggerFactory.getLogger(OssUploadUtil.class);
     
     
     
     
        private static final String accessKeyId = OSSProperties.getAccessKey();
        private static final String accessKeySecret =OSSProperties.getSecretKey();
        private static final String endpoint =OSSProperties.getEndpoint();
        private static final int seconds = OSSProperties.getSeconds();
     
        /**
         * 带进度的上传
         *
         * @param request
         * @return List<String> 返回的文件地址集合
         * @throws Exception
         */
        public static List<String> uploadPicWithProgress(HttpServletRequest request, String bucketName, String ossKey,String  redisKey,RedisService redisService) throws Exception {
            //每次调用都需要实例化一次,实例化的OSSClient shoutDown 一次就不行了
            OSSClient   oSSClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            DefaultMultipartHttpServletRequest req = (DefaultMultipartHttpServletRequest) request;
            request.setCharacterEncoding("UTF-8");
            Map<String, MultipartFile> files = req.getFileMap();
            int i = 0;
            List<String> urlList = Lists.newArrayList();
            for (String key : files.keySet()) {
                String suffix = "";
                MultipartFile file = files.get(key);
     
                /* MultipartFile转File  */
                File f = null;
                try {
                    f = File.createTempFile("tmpFile", null);
                    file.transferTo(f);
                    f.deleteOnExit();
                } catch (Exception e) {
                    e.printStackTrace();
                }
     
                if (file.getOriginalFilename().contains(".")) {
                    suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
                }
                String fileName = System.currentTimeMillis() + i + suffix;
                i++;
                try {
                    PutObjectResult putObjectResult = oSSClient.putObject(new PutObjectRequest(bucketName, ossKey + fileName, f).
                            <PutObjectRequest>withProgressListener(new PutObjectProgressListener(redisKey,redisService)));
                    URL imgUrl =  oSSClient.generatePresignedUrl(bucketName,ossKey + fileName,new Date());
                 String url =  imgUrl.getAuthority()+imgUrl.getPath();
                 logger.debug(url);
                 urlList.add(url);
                } catch (OSSException oe) {
                    logger.error("Caught an OSSException, which means your request made it to OSS, "
                            + "but was rejected with an error response for some reason.Error Message: " + oe.getErrorCode()
                            + "Error Code:" + oe.getErrorCode() + "Request ID:" + oe.getRequestId() + "Host ID:" + oe.getHostId(), oe);
                    throw new OSSException(oe.getErrorMessage(), oe);
                } catch (ClientException ce) {
                    logger.error("Caught an ClientException, which means the client encountered "
                            + "a serious internal problem while trying to communicate with OSS, "
                            + "such as not being able to access the network.Error Message:" + ce.getMessage(), ce);
                    throw new ClientException(ce);
                } finally {
                    oSSClient.shutdown();
                }
            }
            return urlList;
        }
     
        public static class PutObjectProgressListener implements ProgressListener {
            private String redisKey;
            private RedisService redisService;
            private long bytesWritten = 0;
            private long totalBytes = -1;
            private boolean succeed = false;
            private int percent = 0;
     
            //构造方法中加入redis
            public PutObjectProgressListener() {
            }
            public PutObjectProgressListener(String redisKey,RedisService  redisService) {
                this.redisKey = redisKey;
                this.redisService = redisService;
                //首次添加redis值
                redisService.set(redisKey,percent);
            }
     
            @Override
            public void progressChanged(ProgressEvent progressEvent) {
                long bytes = progressEvent.getBytes();
                ProgressEventType eventType = progressEvent.getEventType();
                switch (eventType) {
                    case TRANSFER_STARTED_EVENT:
                        logger.info("Start to upload......");
                        break;
                    case REQUEST_CONTENT_LENGTH_EVENT:
                        this.totalBytes = bytes;
                        logger.info(this.totalBytes + " bytes in total will be uploaded to OSS");
                        break;
                    case REQUEST_BYTE_TRANSFER_EVENT:
                        this.bytesWritten += bytes;
                        if (this.totalBytes != -1) {
                            percent = (int) (this.bytesWritten*100 / this.totalBytes);
                            //将进度percent放入redis中
                            redisService.set(redisKey,percent);
                            logger.info(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
                        } else {
                            logger.info(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
                        }
                        break;
                    case TRANSFER_COMPLETED_EVENT:
                        this.succeed = true;
                        logger.info("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
                        break;
                    case TRANSFER_FAILED_EVENT:
                        logger.info("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
                        break;
                    default:
                        break;
                }
            }
     
            public boolean isSucceed() {
                return succeed;
            }
        }
    }

controller层:

@RestController
    @RequestMapping("/V1/upos/oss/")
    public class FileUploadController extends BaseController {
        private static Logger logger = LoggerFactory.getLogger(FileUploadController.class);
     
        @Autowired
        private RedisService redisService;
     
        /**
         * 阿里云图片BUCKET
         */
        private final String GOODS_PIC_BUCKET_NAME="goods-item-images";
        /**
         * 阿里云图片默认key
         */
        private final String OSS_KEY="uCan-goods";
        /**
         * 用于存放的上传进度的,redis key 前缀
         */
        private final String U_POS_GOODS_PIC="U_POS_GOODS_PIC:";
     
        /**
         * 上传文件
         * @param request
         * @return
         * @throws Exception
         */
        @RequestMapping("upload.do")
        @ResponseBody
        public Object uploadSection(HttpServletRequest request) throws Exception {
            String redisKey = request.getHeader("ucanPicId");
            if(StringUtils.isEmpty(redisKey)){
                    return ErrorResponse.newInstance("上传uCanPicId不能为空!!");
            }
     
            //上传进度同时_往redis中存进度
            List<String> urlList=  OssUploadUtil.uploadPicWithProgress(request,GOODS_PIC_BUCKET_NAME,OSS_KEY,U_POS_GOODS_PIC+redisKey,redisService);
     
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("url","http://"+urlList.get(0));
            return SuccessResponse.newInstance(jsonObject);
        }
     
        /**
         * 获取实时长传进度
         * @return
         */
        @RequestMapping ("percent.do")
        public Object getUploadPercent(@RequestBody JSONObject jsonObject){
            String uCanPicId = Objects.isNull(jsonObject.get("ucanPicId")) ? "":jsonObject.get("ucanPicId").toString();
            if(StringUtils.isEmpty(uCanPicId)){
                return ErrorResponse.newInstance("上传uCanPicId不能为空!!");
            }
            String redisKey = U_POS_GOODS_PIC+uCanPicId;
     
            int percent = redisService.get(redisKey) == null ? 0: Integer.valueOf(redisService.get(redisKey).toString()).intValue();
     
            //避免死循环请求,每次请求,如果上传进度是0,则加一,当连续调用20次依然为0的时候则返回异常
            String countKey = redisKey+"_COUNT";
            if(percent == 0){
                redisService.incrementBy(countKey,1L);
            }
            int count = redisService.get(countKey) == null ? 0: Integer.valueOf(redisService.get(countKey).toString()).intValue();
            if(count > 20){
                return ErrorResponse.newInstance("上传异常,进度为0!!!");
            }
            if(percent >= 100){
                //上传进度到100的时候——————删除该redis值
                redisService.delete(redisKey);
                //上传进度到100的时候——————删除该redis值
                redisService.delete(countKey);
            }
            JSONObject result = new JSONObject();
            result.put("percent",percent);
            return SuccessResponse.newInstance(result);
        }
    }

所需要的maven依赖:

<!--OSS 阿里对象存储 SDK-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>2.8.3</version>
            </dependency>
            <!--文件上传-->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.3</version>
            </dependency>

补充:在使用spring boot 上传文件的时候,还需要配置 MultipartResolver,如果是其他项目则可以在xml里配置:

<!-- 定义文件上传解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设定默认编码 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
        <property name="maxUploadSize" value="5242880"></property>
        <!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
        <property name="maxInMemorySize" value="40960"></property>
        <!-- 上传文件的临时路径 -->
        <property name="uploadTempDir" value="fileUpload/temp"></property>
        <!-- 延迟文件解析 -->
        <property name="resolveLazily" value="true"/>
    </bean>

如果是spring boot 则可以通过下面这种方式注入,两者本质是一样的,只是方式不同:

@Component("multipartResolver")
    public class MultipartResolver  extends CommonsMultipartResolver {
     
        private int maxUploadSize = 104857600;
     
        private int maxInMemorySize = 4096;
     
        public int getMaxUploadSize() {
            return maxUploadSize;
        }
     
        public void setMaxUploadSize(int maxUploadSize) {
            this.maxUploadSize = maxUploadSize;
        }
     
        public int getMaxInMemorySize() {
            return maxInMemorySize;
        }
     
        @Override
        public void setMaxInMemorySize(int maxInMemorySize) {
            this.maxInMemorySize = maxInMemorySize;
        }
    }

补充:

如果有需要可以看一下这位兄弟的写的,我们知道一个用户登录的时候的请求是只有一个唯一的sessionId的,如果是前后端分离的情况下再使用 session 的方式去保存和记录对应的 百分比,那么从用户请求 -----> 到前端服务-----> 后端服务 ,跨域请求的情况下就会导致同一个用户的请求最终传的后端的时候 session 没有保证是唯一的了,所以在这里我使用redis来保存进度,key值是前端传给我的,为了保证key值的唯一性,可以使用用户登录之后的cookies加上当前的时间戳来生成,最终在改张图片上传完成之后再将该key删掉就ok了
————————————————
版权声明:本文为CSDN博主「代码也文艺」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37107280/article/details/81326738

aliyun-oss 通过redis来实现跨域上传图片到阿里 OSS并回显进度条的更多相关文章

  1. ueditor富文本编辑器跨域上传图片解决办法

    在使用百度富文本编辑器上传图片的过程中,如果是有一台单独的图片服务器就需要将上传的图片放到图片服务器,比如在a.com的编辑器中上传图片,图片要保存到img.com,这就涉及到跨域上传图片,而在ued ...

  2. php 之跨域上传图片

    因为要将所有上传的图片上传到一台独立的图片服务器上面,js上传时存在跨域问题,网上找到这种,通过php curl方式,将图片重新发送到另外一台服务器上保存,并返回图片路径!这种方式存在一定问题:1,上 ...

  3. 项目二(业务GO)——跨域上传图片(请求接口)

    之前,就听过“跨域上传”图片的问题,只是疏于研究,也就一再搁置,直至今天再次遇见这个不能避免的“坑”,才不得不思考一下,怎么“跨域上传”图片或者文件? 问题来源: 何为“跨域”? ——就是给你一个接口 ...

  4. django —— KindEditor - 跨域上传图片

    #跨域上传方法 def frontupload(request): if request.method == 'POST': item = {} file = request.FILES.get('i ...

  5. iframe跨域上传图片

    方案一:用jquery的$.post异步提交,然后把返回来的值用jquery填充到隐藏域中.可是$.post不支持跨域. jQuery.ajax()支持get方式的跨域,这其实是采用jsonp的方式来 ...

  6. ajax 异步 跨域上传图片

    客户端 <label for="text">名称</label> <input type="text" id="text ...

  7. ajax跨域上传图片

    前台页面 var data = new FormData(); data.append('file', file); data.append('app', 'goods'); $.ajax({ url ...

  8. kindeditor4跨域上传图片解决

    项目中正在使用kindeditor, 版本号4.1.10 非常多公司的图片会走CDN,须要单独的一台图片上传服务如:(upload.268xue.com) kindeditor上传图片的简单内部流程: ...

  9. webservice跨域上传图片

    1.上传文件,在一般处理程序中处理 //1.接收post过来的文件 HttpPostedFile file = context.Request.Files[]; || file.ContentLeng ...

随机推荐

  1. 2019-2020-1 20199305《Linux内核原理与分析》第五周作业

    系统调用的三层机制(上) (一)用户态.内核态和中断 (1)Intel x86 CPU有4种不同的执行级别 分别是0.1.2.3,数字越小,特权越高.Linux操作系统中只是采用了其中的0和3两个特权 ...

  2. 66000][12505] Listener refused the connection with the following error: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor oracle.n et.ns.NetException: Listener refuse

    新装的idea开发工具后连接数据库出现如题所示错误. 1.网上搜了不少的文章,没有解决我的问题.后来细心看了一下url: 一开始url是这样子的. jdbc:oracle:thin:@:s21_pdb ...

  3. ReactNative: ReactNative初始项目的结构

    一.介绍 初学RN,一切皆新.在上篇中成功地创建并运行了一个React-Native项目,这个demo的基本结构都是系统已经创建好的,开发者在此结构下完成自己的开发即可.分别用Xcode和WebSto ...

  4. MySQL变量介绍和用法简介

    目录 一.用户变量 1.1.用户变量定义 1.2.用户变量用法 二.系统变量 2.1 系统变量简单介绍 2.2 系统变量用法简介 本博客介绍一下MySQL中变量的用法和注意细节 @ 一.用户变量 1. ...

  5. 如何将Javaweb工程的访问协议由http改为https及通过域名访问?

    将javaweb工程的http访问协议更改为https,需要做一下几部操作: 通过jre生成证书 调整tomcat的配置 调整工程的web.xm配置 具体详细过程如下: 一.生成证书 打开cmd切换到 ...

  6. Dubbo+Zookeeper实现简单的远程方法调用示例

    1. Dubbo介绍 示例代码:Github 1.1 RPC Remote Procedure Call:远程过程调用 1.2 Dubbo架构 Subscribe 订阅:签署:赞成 Monitor 监 ...

  7. Python中字符的编码与解码

    1 文本和字节序列 我们都知道字符串,就是由一些字符组成的序列构成串,那么字符又是什么呢?计算机只能识别二进制的东西,那么计算机又为什么会显示我们的汉字,或者是某个字母呢? 由于最早发明使用计算机是美 ...

  8. c#日期和时间戳互转

    using System; using System.Collections.Generic; using System.Data; using System.Reflection; namespac ...

  9. jquery中的ajax请求到php(学生笔记)

    首先ajax的基本语法基础.(必须得引入一个jquery文件,下面的例子展示用了网上的jquery文件,要联网.) 2.请求成功(复制代码运行观察效果) <!DOCTYPE html> & ...

  10. 数据类型和特殊类型-C#

    参考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1.集合set:纯粹的数据集合 2.线性结构:一对一的,数组 3.树形结构: ...