阿里OSS对象存储,实现图片上传进度显示ProgressListener;

想了解阿里OSS对象存储,实现图片上传的内容的可看我的另一篇博客,博客中有完整代码,这篇博客是以上一篇阿里OSS对象存储博客为基础,只写一些与进度有关的内容,细心往下看js代码中有需要注意的地方!

实现方案:

通过ProgressListener类获取进度信息时时存入session,页面通过ajax轮询时时获取session中的数据通过<progress></progress>标签显示;

在这个OSSUploadUtil类中增加一个内部类 PutObjectProgressListener 继承ProgressListener;

这个类PutObjectProgressListener就是实现进度条的核心类,重新这个progressChanged方法,此方法就是实现进度的核心方法,图片进度会通过这个方法时时写入session中;

在类OSSUploadUtil中的这个putObject方法中把

      【 PutObjectRequest request = new PutObjectRequest(
            config.getBucketName(), fileName, input,
             meta); //创建上传请求
            ossClient.putObject(request);】

       这段代码替换成:

      【PutObjectResult putObjectResult = ossClient
                    .putObject(new PutObjectRequest(config.getBucketName(),
                            fileName, f)
                            .<PutObjectRequest> withProgressListener(new PutObjectProgressListener(
                                    request1.getSession(), sum))); 】

进度核心方法内部类:

public static class PutObjectProgressListener implements ProgressListener
    {
        private HttpSession session;
        private long bytesWritten = 0;
        private long totalBytes = -1;
        private boolean succeed = false;
        private int percent = 0;
        int sum = 0;

        // 构造方法中加入session
        public PutObjectProgressListener()
        {
        }

        public PutObjectProgressListener(HttpSession mSession, int sum)
        {
            this.session = mSession;
            this.sum = sum;
            session.setAttribute("upload_percent", 0);
            session.setAttribute("upload_sum", sum);
            System.out
                    .println("====================================================");
            System.out.println("sum:" + sum);
        }

        @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.0 / this.totalBytes);
                        // 将进度percent放入session中
                        session.setAttribute("upload_percent", percent);
                    }
                    else
                    {
                    }
                    break;
                case TRANSFER_COMPLETED_EVENT:
                    this.succeed = true;

                    break;
                case TRANSFER_FAILED_EVENT:

                    break;
                default:
                    break;
            }

//控制台打印进度            

System.out.println("percent:" + percent);

        }

        public boolean isSucceed()
        {
            return succeed;
        }
    }

完整OSSUploadUtil代码(其余有关OSS上传的代码请看另一篇博客):

package com.st.weixin.common;

/**
 * Project Name: 液化天然气车用气瓶智慧监测系统
 * 
 * 
 * FileName: PageController Author: zq Date: 2018/5/2
 * 
 * @since: 1.0.0 Copyright (C), 2015-2018, 坦程物联网有限公司
 */

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

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.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.GenericRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

/**
 *
 * @ClassName: OSSUploadUtil
 * @Description: 阿里云OSS文件上传工具类

 * @author AggerChen
 * 2016年11月3日 下午12:03:24
 */
public class OSSUploadUtil
{

    private static OSSConfig config = null;

    /**
     *
     * @MethodName: uploadFile
     * @Description: OSS单文件上传

     * @param file
     * @param fileType 文件后缀
     * @return String 文件地址
     */
    public static String uploadFile(MultipartFile file, String fileType,
            String oSSConfigkey, HttpServletRequest request, int sum)
    {
        config = config == null ? new OSSConfig() : config;
        String fileName = config.getPicLocation1(oSSConfigkey)
                + UUID.randomUUID().toString().toUpperCase().replace("-", "")
                + "." + fileType; // 文件名,根据UUID来
        return putObject(file, fileType, fileName, request, sum);
    }

    /**
     *
     * @MethodName: updateFile
     * @Description: 更新文件:只更新内容,不更新文件名和文件地址。

     *      (因为地址没变,可能存在浏览器原数据缓存,不能及时加载新数据,例如图片更新,请注意)
     * @param file
     * @param fileType
     * @param oldUrl
     * @return String
     */
    public static String updateFile(CommonsMultipartFile file, String fileType,
            String oldUrl, HttpServletRequest request, int sum)
    {
        String fileName = getFileName(oldUrl);
        if (fileName == null)
            return null;
        return putObject(file, fileType, fileName, request, sum);
    }

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

    /**
     *
     * @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: putObject
     * @Description: 上传文件
     * @param file
     * @param fileType
     * @param fileName
     * @return String
     */
    private static String putObject(MultipartFile file, String fileType,
            String fileName, HttpServletRequest request1, int sum)
    {
        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);
            InputStream input = file.getInputStream();
            ObjectMetadata meta = new ObjectMetadata(); // 创建上传Object的Metadata
            meta.setContentType(OSSUploadUtil.contentType(fileType)); // 设置上传内容类型
            meta.setCacheControl("no-cache"); // 被下载时网页的缓存行为
            /* ========================================================= */
            /* MultipartFile转File */
            File f = null;
            try
            {
                f = File.createTempFile("tmp", null);
                file.transferTo(f);
                f.deleteOnExit();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

            /*
             * 这里用带进度条的OSS上传
             * 将session传入PutObjectProgressListener的构造中!官网例子是没有这个操作的 注意new
             * PutObjectRequest()的第三个参数是File而不是官网介绍的FileInputStream,否则获取不到进度.
             */

            PutObjectResult putObjectResult = ossClient
                    .putObject(new PutObjectRequest(config.getBucketName(),
                            fileName, f)
                            .<PutObjectRequest> withProgressListener(new PutObjectProgressListener(
                                    request1.getSession(), sum)));

            // PutObjectRequest request = new PutObjectRequest(
            // config.getBucketName(), fileName, input,
            // meta); //创建上传请求
            // ossClient.putObject(request);

            url = config.getEndpoint().replaceFirst("http://",
                    "http://" + config.getBucketName() + ".")
                    + "/" + fileName; // 上传成功再返回的文件路径

            System.out.println("url:" + url);
            /* ========================================================== */

        }
        catch (OSSException oe)
        {
            System.out
                    .println("--com.st.weixin.common.OSSUploadUtil---1-------");
            System.out.println(oe.getMessage());
            System.out.println(oe.getErrorCode());
            System.out.println(oe.getClass());
            System.out.println(oe.getStackTrace());

            oe.printStackTrace();
            return null;
        }
        catch (ClientException ce)
        {
            System.out
                    .println("---com.st.weixin.common.OSSUploadUtil--2-------");
            System.out.println(ce.getMessage());
            System.out.println(ce.getErrorCode());
            System.out.println(ce.getClass());
            System.out.println(ce.getStackTrace());
            ce.printStackTrace();
            return null;
        }
        catch (FileNotFoundException e)
        {
            System.out
                    .println("---com.st.weixin.common.OSSUploadUtil--3-------");
            System.out.println(e.getMessage());
            System.out.println(e.getClass());
            System.out.println(e.getStackTrace());
            e.printStackTrace();
            return null;
        }
        catch (IOException e)
        {
            System.out
                    .println("----com.st.weixin.common.OSSUploadUtil-4-------");
            System.out.println(e.getMessage());
            System.out.println(e.getClass());
            System.out.println(e.getStackTrace());
            e.printStackTrace();
        }
        catch (Exception e)
        {
            System.out
                    .println("----com.st.weixin.common.OSSUploadUtil-5-------");
            System.out.println("309行e.getCause()" + e.getCause());
            System.out.println("309行e.getClass()" + e.getClass());
            System.out.println("309行e.getLocalizedMessage()"
                    + e.getLocalizedMessage());
            System.out.println("309行e.getMessage()" + e.getMessage());
            System.out.println("309行e.getSuppressed()" + e.getSuppressed());
            e.printStackTrace();
        }
        finally
        {
            ossClient.shutdown();

        }
        return url;
    }

    /**
     *
     * @MethodName: contentType
     * @Description: 获取文件类型
     * @param fileType
     * @return String
     */
    private static String contentType(String fileType)
    {
        fileType = fileType.toLowerCase();
        String contentType = "";
        if (fileType.equals("bmp"))
        {
            contentType = "image/bmp";

        }
        else if (fileType.equals("gif"))
        {
            contentType = "image/gif";

        }
        else if (fileType.equals("png") || fileType.equals("jpeg")
                || fileType.equals("jpg"))
        {
            contentType = "image/jpeg";

        }
        else if (fileType.equals("html"))
        {
            contentType = "text/html";

        }
        else if (fileType.equals("txt"))
        {
            contentType = "text/plain";

        }
        else if (fileType.equals("vsd"))
        {
            contentType = "application/vnd.visio";

        }
        else if (fileType.equals("ppt") || fileType.equals("pptx"))
        {
            contentType = "application/vnd.ms-powerpoint";

        }
        else if (fileType.equals("doc") || fileType.equals("docx"))
        {
            contentType = "application/msword";

        }
        else if (fileType.equals("xml"))
        {
            contentType = "text/xml";

        }
        else if (fileType.equals("mp4"))
        {
            contentType = "video/mp4";

        }
        else
        {
            contentType = "application/octet-stream";

        }
        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<String>();
        for (String url : fileUrls)
        {
            names.add(getFileName(url));
        }
        return names;
    }

    public static class PutObjectProgressListener implements ProgressListener
    {
        private HttpSession session;
        private long bytesWritten = 0;
        private long totalBytes = -1;
        private boolean succeed = false;
        private int percent = 0;
        int sum = 0;

        // 构造方法中加入session
        public PutObjectProgressListener()
        {
        }

        public PutObjectProgressListener(HttpSession mSession, int sum)
        {
            this.session = mSession;
            this.sum = sum;
            session.setAttribute("upload_percent", 0);
            session.setAttribute("upload_sum", sum);
        }

        @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.0 / this.totalBytes);
                        // 将进度percent放入session中
                        session.setAttribute("upload_percent", percent);
                    }
                    else
                    {
                    }
                    break;
                case TRANSFER_COMPLETED_EVENT:
                    this.succeed = true;

                    break;
                case TRANSFER_FAILED_EVENT:

                    break;
                default:
                    break;
            }

           //图片进度打印控制台 

          System.out.println("percent:" + percent);

        }

        public boolean isSucceed()
        {
            return succeed;
        }
    }


}
 

控制类代码:

  public ModelAndView selectUploadPercent(HttpServletRequest request,HttpServletResponse response){

         HttpSession session = request.getSession();

         //图片上传进度
         int percent = session.getAttribute("upload_percent") == null ? 0:                                                                                                       Integer.parseInt(session.getAttribute("upload_percent").toString());

         //第几张图片
         int sum = session.getAttribute("upload_sum") == null ? 0: Integer.parseInt(session.getAttribute("upload_sum").toString());

        //图片全部上传结束

         int end = session.getAttribute("upload_end") == null ? 0: Integer.parseInt(session.getAttribute("upload_end").toString());
         String jsonStr = "{percent:'+percent+',sum:'+sum+',end:'+end+'}";
         Map<String, Integer> map = new HashMap<String, Integer>();
         try
         {
             map.put("percent",percent);
             map.put("sum",sum);
             map.put("end",end);
             JSONArray json1 = JSONArray.fromObject(map);
             //将json数据返回
             response.getWriter().write(json1.toString());
         }
         catch (Exception e)
         {
             
             e.printStackTrace();
         }
         return null;
     }

 //数据复原
 public void  clearUploadPercent(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
{
  HttpSession session = request.getSession();
  session.setAttribute("upload_percent",0);
  session.setAttribute("upload_sum",1);
  session.setAttribute("upload_end",0);

  Map<String, Integer> map = new HashMap<String, Integer>();
  map.put("percent",0);
  map.put("sum", 0);
  map.put("end", 0);
  JSONArray json1 = JSONArray.fromObject(map);
  response.getWriter().write(json1.toString());

}

页面进度标签:

<div
                style="width: 400px; height: 20px; text-align: center; left: 1%; top: 43%; position: absolute;">
                <label style="color: blue">
                    上传第
                    <span id="sum"></span>张图:
                </label>
                <progress id="percent" type="circle" value="" max="100">

                </progress>
                <span id="per" style="color: blue; margin-left: 5px"></span>

   </div>

js:

js中需要注意两个问题:

   1.写 setInterval或seTimeout这个方法时 方法中直接写要运行的函数名,并赋值一个变量,这个变量必须是全局变量;

   2.  在ajax中 同步参数这个async必须是false;[ async : false, ],否则pc端游览器正常,手机端游览器报error错误;这个错误并不是数据       格式不对而引起的,而这是因为手机端在轮询调取ajax时 ajax没有同步而造成了互相之间冲突;

js代码:

//每100ms获取一次图片上传进度
var intervalId;
function interval() {
    intervalId = window.setInterval(showPercent, 100)
}

//获取图片进度数据
function showPercent() {
    $.ajax( {
        type : "POST",
        contentType : false,
        async : false,
        cache : false,
        url : "intoNetTCSubmit.htm?method=selectUploadPercent",
        dataType : "json",
        success : function(data) {
            console.log(data);
            var end = 0;
            var per = 0;
            end = data[0].end;
            per = data[0].percent + "%"
            console.log(per);
            console.log("end:" + end);
            $("#percent").val(data[0].percent);//图片上传进度
        $("#sum").html(data[0].sum == 0 ? 1 : data[0].sum);//第几张图片
        $("#per").html(per);
        if (end == '-1') { //图片上传结束标识
            stopInterval();
            //图片上传完成session重置
        clearPercent();
    }
},
error : function(data) {
    console.log(data);
    stopInterval();
    clearPercent();
    alert("ajax异常!!!");

}
    });
}

//清除进度数据
function clearPercent() {

$.ajax( {
        type : "POST",
        contentType : false,
        async : false,
        cache : false,
        url : "intoNetTCSubmit.htm?method=clearUploadPercent",
        dataType : "json",
        success : function(data) {
        console.log("ddd:"+data);
        },
    });
}

//清除时间
function stopInterval() {
  window.clearInterval(intervalId);
}

猜你喜欢

转载自blog.csdn.net/qq_15204179/article/details/81665950