📄 uploadddxc.java
字号:
package com.redmoon.kit.util;
import java.io.*;
import java.util.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import cn.js.fan.util.ErrMsgException;
import cn.js.fan.util.file.FileUtil;
import org.apache.log4j.Logger;
import cn.js.fan.web.Global;
/**
* <p>Title: 支持断点续传</p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/
public class UploadDdxc {
public Logger logger = Logger.getLogger(UploadDdxc.class.getName());
public long maxFileSize = 1024 * 600; // 默认为600M
// 在JDK1.5中已经出现concurrentmap比下面的方式,更利于高效同步
static Map uploadFileInfos = Collections.synchronizedMap(new HashMap());
// Vector fileList = new Vector();
final String upload_type_file_header = "TYPE_FILE_HEADER";
final String upload_type_thread_header = "TYPE_THREAD_HEADER";
final String upload_type_segment = "TYPE_SEGMENT";
final String upload_type_file_finished = "TYPE_FILE_FINISHED";
final String thread_segment_ok = "Thread segment ok";
final String thread_header_ok = "Thread header ok";
// final String post_info_ok = "Post info ok";
public final String file_finished_ok = "File finished ok";
public final String file_header_ok = "File header ok";
final String file_count_exceed_max = "Too many files are being uploaded. Please wait.";
public String visualPath = ""; // 用于forum的断点续传,因为forum中上传时filepath=upfile/webedit/...,而实际路径为forum/upfile/webedit/...,所以需设visualPath = "forum/"
public UploadDdxc() {
UploadReaper.initInstance(UploadReaper.getReapInterval());
}
public Map getUploadFileInfos() {
return uploadFileInfos;
}
public String receive(ServletContext application,
HttpServletRequest request) throws ErrMsgException {
FileUpload fu = doUpload(application, request);
return op(request, fu);
}
public FileUpload doUpload(ServletContext application,
HttpServletRequest request) throws
ErrMsgException {
FileUpload fu = new FileUpload();
fu.setMaxFileSize((int) maxFileSize); // 每个文件最大30000K 即近300M
// String[] ext = {"htm", "gif", "bmp", "jpg", "png", "rar", "doc", "hs", "ppt", "rar", "zip", "jar"};
// fu.setValidExtname(ext);
int ret = 0;
try {
ret = fu.doUpload(application, request);
if (ret == fu.RET_TOOLARGESINGLE) {
throw new ErrMsgException(fu.getErrMessage());
}
if (ret == fu.RET_INVALIDEXT) {
throw new ErrMsgException(fu.getErrMessage());
}
} catch (IOException e) {
logger.error("doUpload:" + e.getMessage());
}
return fu;
}
public String op(HttpServletRequest request, FileUpload fu) throws ErrMsgException {
String uploadType = fu.getFieldValue("uploadType");
if (uploadType == null) {
logger.error("want uploadType");
Enumeration enu = fu.getFields();
while (enu.hasMoreElements()) {
String key = (String)enu.nextElement();
logger.info("op: key=" + key + " value=" + fu.fields.get(key));
}
return "want uploadType";
}
String re = "";
if (uploadType.equals(upload_type_file_header)) {
re = ReceiveUploadFileHeader(request, fu);
} else if (uploadType.equals(upload_type_thread_header)) {
re = ReceiveUploadThreadHeader(fu);
} else if (uploadType.equals(upload_type_segment)) {
re = ReceiveUploadThreadFileSegment(fu);
} else if (uploadType.equals(upload_type_file_finished)) {
re = ReceiveUploadFileFinished(request, fu);
}
else
throw new ErrMsgException("Upload type error.");
return re;
}
public void setMaxFileSize(long maxFileSize) {
this.maxFileSize = maxFileSize;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public long getMaxFileSize() {
return maxFileSize;
}
public boolean isDebug() {
return debug;
}
/**
* ReceiveUploadFileHeader(FileUpload fu)
*/
public String ReceiveUploadFileHeader(HttpServletRequest request, FileUpload fu) throws ErrMsgException {
// 检查总的上传文件是否已达到最大值,如果是则reap,reap后如果还是最大值,则抛出异常
// System.out.println("ReceiveUploadFileHeader v size=" + uploadFileInfos.size());
if (uploadFileInfos.size()>=Global.maxUploadingFileCount)
return file_count_exceed_max;
// 接收文件,如果是文件头,则将其记录于fileList
String fileId = fu.getFieldValue("fileId");
if (fileId==null)
throw new ErrMsgException("want fileId");
String clientFilePath = fu.getFieldValue("clientFilePath");
// logger.info("clientFilePath=" + clientFilePath);
String filepath = visualPath + fu.getFieldValue("filepath");
UploadFileInfo ufi = new UploadFileInfo();
ufi.setFileId(fileId);
ufi.setClientFilePath(clientFilePath);
ufi.setFilePath(filepath); // 保存文件的路径
uploadFileInfos.put(fileId, ufi);
// logger.info("ReceiveUploadFileHeader fileId=" + fileId);
return file_header_ok;
}
public String ReceiveUploadThreadHeader(FileUpload fu) throws
ErrMsgException {
// 如果是线程的头部
String fileId = fu.getFieldValue("fileId");
if (fileId == null)
throw new ErrMsgException("want fileId");
String sBlockId = fu.getFieldValue("blockId");
if (sBlockId == null)
throw new ErrMsgException("want blockId");
int blockId = Integer.parseInt(sBlockId);
UploadThreadInfo uti = new UploadThreadInfo();
uti.setFileId(fileId);
uti.setBlockId(blockId);
// 记录于UploadFileInfo中
UploadFileInfo ufi = (UploadFileInfo) uploadFileInfos.get(fileId);
if (ufi == null) {
logger.error("ReceiveUploadThreadHeader fileId=" + fileId);
throw new ErrMsgException(
"There are no file header for this thread.");
}
ufi.addUploadThreadInfo(uti);
try {
// 创建文件块
String blockPath = fu.getTmpPath() + ufi.getBlockName(blockId);
File file = new File(blockPath);
if (!(file.exists()))
file.createNewFile(); // 如果文件不存在,创建此文件
} catch (IOException e) {
logger.error("创建块文件失败!" + e.getMessage());
}
return thread_header_ok;
}
public String ReceiveUploadThreadFileSegment(FileUpload fu) throws
ErrMsgException {
String fileId = fu.getFieldValue("fileId");
if (fileId == null)
throw new ErrMsgException("want fileId");
// 如果是线程的segment,则写至文件块中的相应的位置
String sBlockId = fu.getFieldValue("blockId");
if (sBlockId == null)
throw new ErrMsgException("want blockId!");
String sOffset = fu.getFieldValue("offset");
if (sOffset == null)
throw new ErrMsgException("want offset!");
String sLength = fu.getFieldValue("length");
if (sLength == null)
throw new ErrMsgException("want length!");
int blockId = Integer.parseInt(sBlockId);
int offset = Integer.parseInt(sOffset);
int length = Integer.parseInt(sLength);
Vector v = fu.getFiles();
if (v.size() > 0) {
FileInfo fi = (FileInfo) v.get(0);
String tmpPath = fi.getTmpFilePath();
File file = new File(tmpPath);
// 长度不相等,说明上传过程中出错!要求客户端重新再传
if (length != file.length()) {
logger.error("segment length=" + length + " tmp file length=" + file.length());
throw new ErrMsgException("segment error");
}
// 追加数据至fileId文件的blockId块
UploadFileInfo ufi = (UploadFileInfo) uploadFileInfos.get(fileId);
if (ufi == null)
throw new ErrMsgException("want thread header");
String blockPath = fu.getTmpPath() + ufi.getBlockName(blockId);
try {
RandomAccessFile rf = new RandomAccessFile(blockPath, "rw");
// 定义一个类RandomAccessFile的对象,并实例化
// rf.seek(rf.length()); // 将指针移动到文件末尾
// 当传输过程中出错,或者传输中途被取消时,就有可能会使得续传时,开始处不一定是在文件的末尾
// 因此上句不能使用,应该使用offset作为文件指针的偏移量
rf.seek(offset);
File tmpFile = new File(fi.getTmpFilePath());
// FileInputStream fis = new FileInputStream(fi.getTmpFilePath());
FileInputStream fis = new FileInputStream(tmpFile);
BufferedInputStream bis = new BufferedInputStream(fis); // 读取文件的BufferedRead对象
byte[] buf = new byte[1024];
int len = 0;
while ((len = bis.read(buf)) != -1) {
rf.write(buf, 0, len);
}
bis.close();
fis.close(); // 关闭文件
rf.close(); // 关闭文件流
tmpFile.delete(); // 删除上传得到的临时文件
} catch (IOException e) {
logger.error("ReceiveUploadThreadFileSegment: " + e.getMessage());
}
} else
throw new ErrMsgException("want file");
return thread_segment_ok;
}
public String ReceiveUploadFileFinished(HttpServletRequest request, FileUpload fu) throws
ErrMsgException {
// 如果是文件的结束,则将文件整理并拷贝至相应的目录,然后删除临时文件
String fileId = fu.getFieldValue("fileId");
if (fileId == null)
throw new ErrMsgException("want fileId");
UploadFileInfo ufi = (UploadFileInfo) uploadFileInfos.get(fileId);
// logger.info("ReceiveUploadFileFinished:" + ufi.getFilePath() + " ---- " + ufi.getClientFilePath());
if (ufi == null)
throw new ErrMsgException("want thread header");
// 在UploadFIleInfo指定的保存位置写入文件
String fullSavePath = ufi.getFullSavePath(fu.getRealPath());
try {
// 创建文件块
File file = new File(fullSavePath);
// logger.info("fullSavePath" + fullSavePath);
if (!(file.exists()))
file.createNewFile(); //如果文件不存在,创建此文件
} catch (IOException e) {
logger.error("创建文件失败!" + e.getMessage());
}
ufi.setState(ufi.state_finished);
Vector v = ufi.getUploadThreadInfos();
int size = v.size();
// 组合文件
for (int i = 0; i < size; i++) {
UploadThreadInfo uti = (UploadThreadInfo) v.get(i);
String blockPath = fu.getTmpPath() +
ufi.getBlockName(uti.getBlockId());
if (debug) {
logger.info(uti.getFileId() + " begin=" + uti.getBegin() +
" end=" + uti.getEnd());
logger.info("fullSavePath=" + fullSavePath);
logger.info("blockPath=" + blockPath);
}
FileUtil.AppendFile(fullSavePath, blockPath);
// 删除上传线程产生的临时文件
File file = new File(blockPath);
file.delete();
}
// 从链表中删除UploadFileInfo
uploadFileInfos.remove(fileId);
return file_finished_ok;
}
private boolean debug = true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -