Structs下上传文件进度显示

两种思路,一种是使用plupload插件,使用插件就比较简单,进度在前端实现,plupload记录发送的文件大小并提供函数。具体可参考http://www.plupload.com/官网。

另一种就是在后台监听接收数据,前台使用ajax轮回实时读取展示进度信息。

本文旨在叙述第二种方法后台方法。

环境:前台上传插件http://www.jq22.com/jquery-info13450,后台Structs。(注插件提供了springmvc版本的进度显示)

1、定义返回信息实体类


public class UploadStatus {
    private long bytesRead;//已读数据
    private long contentLength;//文件总数据
    private long items;//第几个文件
    private long startTime = System.currentTimeMillis();//开始时间
    private long useTime = System.currentTimeMillis();//已用时间
    private int percent;//完成百分比
    
    public long getBytesRead() {
        return bytesRead;
    }
    public void setBytesRead(long bytesRead) {
        this.bytesRead = bytesRead;
    }
    public long getContentLength() {
        return contentLength;
    }
    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }
    public long getItems() {
        return items;
    }
    public void setItems(long items) {
        this.items = items;
    }
    public long getStartTime() {
        return startTime;
    }
    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
    public long getUseTime() {
        return useTime;
    }
    public void setUseTime(long useTime) {
        this.useTime = useTime;
    }
    public int getPercent() {
        return percent;
    }
    public void setPercent(int percent) {
        this.percent = percent;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "UploadStatus [percent=" + percent + ", items=" + items + "]";
    }
}


2、创建监听类实现ProgressListener


import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.ProgressListener;

public class UploadListener implements ProgressListener{
    private HttpSession session;
    public UploadListener(HttpSession session){
        super();
        this.session = session;
        UploadStatus uploadStatus = new UploadStatus();
        session.setAttribute("upload_status", uploadStatus);
    }
    
    @Override
    public void update(long bytesRead, long contentLength, int items) {
        // TODO Auto-generated method stub
        UploadStatus uploadStatus = (UploadStatus) session.getAttribute("upload_status");
        uploadStatus.setBytesRead(bytesRead);
        uploadStatus.setContentLength(contentLength);
        uploadStatus.setItems(items);
        uploadStatus.setUseTime(System.currentTimeMillis()-uploadStatus.getStartTime());
        uploadStatus.setPercent((int)(100*bytesRead/contentLength));
        session.setAttribute("upload_status", uploadStatus);
        
    }
    
}

3、实现MultiPartRequest接口,主要是让自己的监听事件监听上传

package com.cngrain.util;

import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.struts2.StrutsConstants;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;

public class UploadCommonsMultipartResolver implements MultiPartRequest {
    static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);

    // maps parameter name -> List of FileItem objects
    protected Map> files = new HashMap>();

    // maps parameter name -> List of param values
    protected Map> params = new HashMap>();

    // any errors while processing this request
    protected List errors = new ArrayList();

    protected long maxSize;

    @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
    public void setMaxSize(String maxSize) {
        this.maxSize = Long.parseLong(maxSize);
    }

    /**
     * Creates a new request wrapper to handle multi-part data using methods
     * adapted from Jason Pell's multipart classes (see class description).
     * 
     * @param saveDir
     *            the directory to save off the file
     * @param request
     *            the request containing the multipart
     * @throws java.io.IOException
     *             is thrown if encoding fails.
     */
    public void parse(HttpServletRequest request, String saveDir) throws IOException {
        try {
            processUpload(request, saveDir);
        } catch (FileUploadException e) {
            LOG.warn("Unable to parse request", e);
            errors.add(e.getMessage());
        }
    }

    private void processUpload(HttpServletRequest request, String saveDir)
            throws FileUploadException, UnsupportedEncodingException {
        for (FileItem item : parseRequest(request, saveDir)) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Found item " + item.getFieldName());
            }
            if (item.isFormField()) {
                processNormalFormField(item, request.getCharacterEncoding());
            } else {
                processFileField(item);
            }
        }
    }

    private void processFileField(FileItem item) {
        LOG.debug("Item is a file upload");

        // Skip file uploads that don't have a file name - meaning that no file
        // was selected.
        if (item.getName() == null || item.getName().trim().length() < 1) {
            LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
            return;
        }

        List values;
        if (files.get(item.getFieldName()) != null) {
            values = files.get(item.getFieldName());
        } else {
            values = new ArrayList();
        }

        values.add(item);
        files.put(item.getFieldName(), values);
    }

    private void processNormalFormField(FileItem item, String charset) throws UnsupportedEncodingException {
        LOG.debug("Item is a normal form field");
        List values;
        if (params.get(item.getFieldName()) != null) {
            values = params.get(item.getFieldName());
        } else {
            values = new ArrayList();
        }

        // note: see http://jira.opensymphony.com/browse/WW-633
        // basically, in some cases the charset may be null, so
        // we're just going to try to "other" method (no idea if this
        // will work)
        if (charset != null) {
            values.add(item.getString(charset));
        } else {
            values.add(item.getString());
        }
        params.put(item.getFieldName(), values);
    }

    private List parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
        DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
        ServletFileUpload upload = new ServletFileUpload(fac);
        upload.setSizeMax(maxSize);
        /* 自己新建监听器 */
        UploadListener progressListener = new UploadListener(servletRequest.getSession());
        upload.setProgressListener(progressListener);// 添加自己的监听器

        return upload.parseRequest(createRequestContext(servletRequest));
    }

    private DiskFileItemFactory createDiskFileItemFactory(String saveDir) {
        DiskFileItemFactory fac = new DiskFileItemFactory();
        // Make sure that the data is written to file
        fac.setSizeThreshold(0);
        if (saveDir != null) {
            fac.setRepository(new File(saveDir));
        }
        return fac;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#
     * getFileParameterNames()
     */
    public Enumeration getFileParameterNames() {
        return Collections.enumeration(files.keySet());
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(
     * java.lang.String)
     */
    public String[] getContentType(String fieldName) {
        List items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List contentTypes = new ArrayList(items.size());
        for (FileItem fileItem : items) {
            contentTypes.add(fileItem.getContentType());
        }

        return contentTypes.toArray(new String[contentTypes.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.
     * lang.String)
     */
    public File[] getFile(String fieldName) {
        List items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List fileList = new ArrayList(items.size());
        for (FileItem fileItem : items) {
            File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
            if (fileItem.isInMemory() && storeLocation != null && !storeLocation.exists()) {
                try {
                    storeLocation.createNewFile();
                } catch (IOException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error("Cannot write uploaded empty file to disk: " + storeLocation.getAbsolutePath(), e);
                    }
                }
            }
            fileList.add(storeLocation);
        }

        return fileList.toArray(new File[fileList.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(
     * java.lang.String)
     */
    public String[] getFileNames(String fieldName) {
        List items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List fileNames = new ArrayList(items.size());
        for (FileItem fileItem : items) {
            fileNames.add(getCanonicalName(fileItem.getName()));
        }

        return fileNames.toArray(new String[fileNames.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#
     * getFilesystemName(java.lang.String)
     */
    public String[] getFilesystemName(String fieldName) {
        List items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List fileNames = new ArrayList(items.size());
        for (FileItem fileItem : items) {
            fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
        }

        return fileNames.toArray(new String[fileNames.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(
     * java.lang.String)
     */
    public String getParameter(String name) {
        List v = params.get(name);
        if (v != null && v.size() > 0) {
            return v.get(0);
        }

        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#
     * getParameterNames()
     */
    public Enumeration getParameterNames() {
        return Collections.enumeration(params.keySet());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#
     * getParameterValues(java.lang.String)
     */
    public String[] getParameterValues(String name) {
        List v = params.get(name);
        if (v != null && v.size() > 0) {
            return v.toArray(new String[v.size()]);
        }

        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
     */
    public List getErrors() {
        return errors;
    }

    /**
     * Returns the canonical name of the given file.
     * 
     * @param filename
     *            the given file
     * @return the canonical name of the given file
     */
    private String getCanonicalName(String filename) {
        int forwardSlash = filename.lastIndexOf("/");
        int backwardSlash = filename.lastIndexOf("\\");
        if (forwardSlash != -1 && forwardSlash > backwardSlash) {
            filename = filename.substring(forwardSlash + 1, filename.length());
        } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
            filename = filename.substring(backwardSlash + 1, filename.length());
        }

        return filename;
    }

    /**
     * Creates a RequestContext needed by Jakarta Commons Upload.
     * 
     * @param req
     *            the request.
     * @return a new request context.
     */
    private RequestContext createRequestContext(final HttpServletRequest req) {
        return new RequestContext() {
            public String getCharacterEncoding() {
                return req.getCharacterEncoding();
            }

            public String getContentType() {
                return req.getContentType();
            }

            public int getContentLength() {
                return req.getContentLength();
            }

            public InputStream getInputStream() throws IOException {
                InputStream in = req.getInputStream();
                if (in == null) {
                    throw new IOException("Missing content in the request");
                }
                return req.getInputStream();
            }
        };
    }

    @Override
    public void cleanUp() {
        // TODO Auto-generated method stub

    }

}

4、.配置struts.xml






5、编写action获取上传信息

    @Action(value = "getStatus", results = { @Result(name = SUCCESS,  type = "json" ) }) 
    public String getStatus(){
        uploadStatus = (UploadStatus)request.getSession().getAttribute("upload_status");
        return SUCCESS;
    }

你可能感兴趣的:(Structs下上传文件进度显示)