• aliyun-oss 通过redis来实现跨域上传图片到阿里 OSS并回显进度条


        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

  • 相关阅读:
    C#匿名类型
    C#中实例Singleton
    Unity Pitfall 汇总
    Unity快捷键
    System.Object
    ExecuteInEditMode
    preview放大镜
    判断当前Selection是否为prefab
    AddComponentMenu
    MenuItem属性
  • 原文地址:https://www.cnblogs.com/lykbk/p/aesdfdfdf456565565.html
Copyright © 2020-2023  润新知