struts2实现文件上传显示进度条效果

网友投稿 228 2023-05-18


struts2实现文件上传显示进度条效果

一. struts2读取进度原理分析(作为草稿存了好久,刚刚发布出来......)

1. 在strut2中控制文件上传信息的类是实现MultiPartRequest接口的JakartaMultiPartRequest

其实第一次看到源文件时我打了个退堂鼓,因为觉得内容太长了,不想看。冷静下来将思路理顺,将分开的各个方法还原到一个方方中中,发现还是很好理解的:

@Override

public void parse(HttpServletRequest request, String saveDir)

throws IOException {

setLocale(request);

     //规定了File文件的格式(如文件名必须是xxFileName,文件类型xxContentType),并定义了File的保存路径     DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);//处理文件上传的servlet

upload.setProgressListener(new FileUploadProgressListener(request)); //为文件上传添加监听 factory.setSizeThreshold(0); //if (saveDir != null

factory.setRepository(new File(saveDir));//临时路径

}

try {

upload.setSizeMax(maxSize);

List items = upload.parseRequest(createRequestContext(request)); //获取所有请求

for (Object obItem : items) {

FileItem item = (FileItem) obItem; //获取每个请求的文件

if (LOG.isDebugEnabled()) {

LOG.debug("Found item" + item.getFieldName());

}

if (item.isFormField()) { //普通表单提交

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();

}

String charset = request.getCharacterEncoding();

if (charset != null) {

values.add(item.getString(charset));

} else {

values.add(item.getString());

}

params.put(item.getFieldName(), values);

} else { //文件上传请求

LOG.debug("Item is a file upload");

if (item.getName() == null

|| item.getName().trim().length() <= 0) {

LOG.debug("No file has been uploded for the filed:"

+ item.getFieldName());

continue;

}

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);

}

}

} catch (FileUploadBase.SizeLimitExceededException e) {

System.out.println("错误1:" + e);

if (LOG.isWarnEnabled()) {

LOG.warn("Request exceeded size limit!", e);

}

String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});

if (!errors.contains(errorMessage)) {

errors.add(errorMessage);

}

} catch (Exception e) {

System.out.println("错误1:" + e);

if (LOG.isWarnEnabled()) {

LOG.warn("Unable to parse request", e);

}

String errorMessage = buildErrorMessage(e, new Object[]{});

if (!errors.contains(errorMessage)) {

errors.add(errorMessage);

}

}

}

2.  文件上传监听文件FileUploadProgressListener.java

public class FileUploadProgressListener implements ProgressListener {

  private final HttpSession session;

  private final DecimalFormat format = new DecimalFormat("#00.0");

  public FileUploadProgressListener(HttpServletRequest request) {

    session = request.getSession();

    FileUploadStatus status = new FileUploadStatus();

    session.setAttribute("uploadStatus", status);

  }

  @Override

  public void update(long pBytesRead, long pContentLength, int pItems) {

    FileUploadStatus uploadStatus = (FileUploadStatus) session.getAttribute("uploadStatus");

    Double uploadRate = (double) (pBytesRead * 100 / pContentLength);

    uploadStatus.setUploadRate(Double.valueOf(format.format(uploadRate)));

    uploadStatus.setReadedBytes(pBytesRead / 1024);

    uploadStatus.setTotalBytes(pContentLength / 1024);

    uploadStatus.setCurrentItems(pItems);

  }

}

3. 添加状态文件:FileUploadStatus.java

public class FileUploadStatus {

private Double uploadRate = 0.0;

private Long readedBytes = 0L;

private Long totalBytes = 0L;

private int currentItems = 0;

private Long uploadSpeed = 0L;

private Long startTime = System.currentTimeMillis();

private Long readedTimes = 0L;

private Long totalTimes = 0L;

// "-1" 错误 "0" 正常 "1" 完成

private String error = "0";

...

setter getter方法

...

}

4. Action类(如果是多文件上传,则将File   FileName   ContentType定义成数组形式即可)

/**

* 利用io流上传文件

*/

public class FileStreamUploadAction extends ActionSupport {

/**

* serialVersionUID作用: ---相当于类的身份证。 序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。

* 有两种生成方式: 一个是默认的1L,比如:private static final long serialVersionUID = 1L;

* 一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如: private static final long

* serialVersionUID = xxxxL;

*/

private static final long serialVersionUID = 1L;

private File image;

private String imageFileName;

private String imageContentType;

private String message;

public String uploadFile() {

FileInputStream in = null;

FileOutputStream out = null;

System.out.println("文件名:" + imageFileName);

try {

this.setNewFileName(imageFileName);

String realPath = ServletActionContext.getServletContext()

.getRealPath("/file");

File filePath = new File(realPath);

if (!filePath.exists()) { // 如果保存的路径不存在则创建

filePath.mkdir();

}

if (image == null) {

message = "上传文件为空";

System.out.println(message);

} else {

File saveFile = new File(filePath, this.getNewFileName());

out = new FileOutputStream(saveFile);

}

in = new FileInputStream(image);

byte[] byt = new byte[1024];

int length = 0;

while ((length = in.read(byt)) > 0) {

out.write(byt, 0, length);

out.flush();

}

message = "上传成功";

System.out.println(message);

} catch (FileNotFoundException e) {

message = "找不到文件!";

e.printStackTrace();

} catch (IOException e) {

message = "文件读取失败!";

e.printStackTrace();

} finally {

closeStream(in, out);

}

return "uploadSucc";

}

public void closeStream(FileInputStream in, FileOutputStream out) {

try {

if (in != null) {

in.close();

}

if (out != null) {

out.close();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

...

setter() getter()

...

}

获取进度的Action

public class FileProgressAction extends ActionSupport {

  private static final long serialVersionUID = 1L;

  private FileUploadStatus uploadStatus;

  public String uploadPercent() {

    HttpSession session = ServletActionContext.getRequest().getSession();

    this.uploadStatus = (FileUploadStatus) session.getAttribute("uploadStatus");

    if (uploadStatus == null) {

      System.out.println("action is null");

      uploadStatus = new FileUploadStatus();

      uploadStatus.setCurrentItems(0);

    }

    return "getPercent";

  }

  public FileUploadStatus getUploadStatus() {

    return uploadStatus;

  }

  public void setUploadStatus(FileUploadStatus uploadStatus) {

    this.uploadStatus = uploadStatus;

  }

}

5.struts.xml中

newFileName

text/html

uploadStatus

二.  进度条显示

View页面设置,利用ajaxfileupload.js来获取文件并进行异步上传,bootstrap中的进度条效果显示进度(利用setInterval间断的获取进度信息来形式一种进度的前进显示)

文件异步上传+进度条





//file的name属性必须设置的与后台Action中file的名称是相同的,否则ajaxFileUpload获取不到文件信息


三、总结

用这种方法获取上传进度有一个缺点:读取进度阶段是文件从指定目录开始在临时文件中存储的过程,而文件上传则是重临时路径下将文件转移到目标路径下,这样就造成了一个时间差,就是读取进度总会比上传文件快,上传的文件越大这个缺点越是明显。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java连接mysql数据库的方法
下一篇:Java集合Map常见问题_动力节点Java学院整理
相关文章

 发表评论

暂时没有评论,来抢沙发吧~