package com.trydone.forum.action;
import com.trydone.core.io.BufferedRandomAccessFile;
import net.jforum.JForumExecutionContext;
import net.jforum.context.RequestContext;
import net.jforum.context.ResponseContext;
import net.jforum.dao.AttachmentDAO;
import net.jforum.entities.Attachment;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import net.jforum.view.forum.common.ViewCommon;
import java.io.IOException;
import java.io.OutputStream;
public class AttachmentAction {
/**
* 下载附件,支持断点续载
*
* @param am
* @param attach net.jforum.entities.Attachment @throws IOException java.io.IOException
*/
public static void downloadAttachment(AttachmentDAO am, Attachment attach) throws IOException {
String filePath = SystemGlobals.getValue(ConfigKeys.ATTACHMENTS_STORE_DIR)
+ "/"
+ attach.getInfo().getPhysicalFilename();
RequestContext request = JForumExecutionContext.getRequest();
ResponseContext response = JForumExecutionContext.getResponse();
BufferedRandomAccessFile raf = new BufferedRandomAccessFile(filePath, "r");
java.io.FileInputStream fis = new java.io.FileInputStream(raf.getFD());
// response.reset();
response.setHeader("Server", "www.trydone.com");
//Accept-Ranges: bytes
response.setHeader("Accept-Ranges", "bytes");
long pos = 0;
long len;
len = raf.length();
//HTTP/1.1 200 OK
if (request.getHeader("Range") != null) //客户端请求的下载的文件块的开始字节
{
//HTTP/1.1 206 Partial Content
response.sendError(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);//.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT); //206
//response.sendError(206,"Partial Content");
//Range: bytes=[文件块的开始字节]-
pos = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
}
//Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
response.setHeader("Content-Length", Long.toString(len - pos));
if (pos != 0) {
//不是从最开始下载,
//响应的格式是:
//Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
response.setHeader("Content-Range", "bytes " + Long.toString(pos) + "-" + Long.toString(len - 1) + "/" + Long.toString(len));
}
//response.setHeader("Connection", "Close"); //如果有此句话不能用 IE 直接下载
//使客户端直接下载
//响应的格式是:
//Content-Type: application/octet-stream
response.setContentType("application/octet-stream");
//为客户端下载指定默认的下载文件名称
//响应的格式是:
//Content-Disposition: attachment;filename="[文件名]"
//response.setHeader("Content-Disposition", "attachment;filename=\"" + filePath.substring(filePath.lastIndexOf("\\") + 1) + "\""); //经测试 RandomAccessFile 也可以实现,有兴趣可将注释去掉,并注释掉 FileInputStream 版本的语句
if (am.isPhysicalDownloadMode(attach.getInfo().getExtension().getExtensionGroupId())) {
response.setContentType("application/octet-stream");
} else {
response.setContentType(attach.getInfo().getMimetype());
}
if (request.getHeader("User-Agent").indexOf("Firefox") != -1) {
response.setHeader("Content-Disposition", "attachment; filename=\""
+ new String(attach.getInfo().getRealFilename().getBytes(SystemGlobals.getValue(ConfigKeys.ENCODING)),
SystemGlobals.getValue(ConfigKeys.DEFAULT_CONTAINER_ENCODING)) + "\";");
} else {
response.setHeader("Content-Disposition", "attachment; filename=\""
+ ViewCommon.toUtf8String(attach.getInfo().getRealFilename()) + "\";");
}
raf.seek(pos);
byte[] b = new byte[1024];
int i;
OutputStream out = response.getOutputStream();
while ((i = raf.read(b)) != -1) {
out.write(b, 0, i);
}
raf.close();
fis.close();
}
}