近日在试用jcifs_1.3.8 实现Java直接读取局域网内共享文件,其实现就像Linux下的SMB协议,感觉挺方便的~ 可是在实现文件下载时发生了一个奇怪的情况:Txt文件可以正常下载,但是多会了几行空行在前面,而其他文件(如Excle)等则会损坏,结果发现是JSP中换行的问题,现在把实验贴上来以防忘记,顺便与大家分享 ^^
1. 下载 jcifs-1.3.8.jar
2. 测试JSP:
<%@ page language="java" pageEncoding="UTF-8"
contentType="text/html; charset=UTF-8" import="jcifs.smb.*,java.io.*,java.util.*,
java.net.URLEncoder,java.net.URLDecoder"
%><%! // --------不能有空行
public java.util.List getFileList(String url){
try {
SmbFile sf = new SmbFile(url);
if(sf!=null){
/*// 仅过滤文件
SmbFile[] files = sf.listFiles(new SmbFilenameFilter(){
public boolean accept(SmbFile dir, String name) throws SmbException {
return name.endsWith(".txt");
}
}); */
SmbFile[] files = sf.listFiles();
if (files != null) {
java.util.List list = new ArrayList();
for (int i = 0; i < files.length; i++){
Map map = new HashMap();
map.put("name", URLEncoder.encode(files[i].getName(),"UTF-8"));
map.put("recordurlall", URLEncoder.encode(files[i].getURL().toString(),"UTF-8"));
list.add(map);
}
return list;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public byte[] getFile(String url){
SmbFileInputStream in = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
in = new SmbFileInputStream(url); // 建立smb文件輸入流
byte buffer[] = new byte[4096];
for(int n = 0; (n = in.read(buffer))>0;){
out.write(buffer, 0, n);
}
return out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
return null;
}
public byte[] getFile2(String url){
SmbFileInputStream in = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmbFile sf = new SmbFile(url); // 建立smb文件輸入流
in = new SmbFileInputStream(sf);
byte[] b = new byte[4096];
int n;
while(( n = in.read( b )) > 0 ) {
out.write(b, 0, n);
}
return out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
return null;
}
public void print(String fileName, HttpServletResponse response, byte[] destFiles) throws Exception{
//檔案名稱
String encodeFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
if(fileName.endsWith(".xls"))
response.setContentType("application/vnd.ms-excel");
else
response.setContentType("text/plain");
//加上下列兩行才可開啟檔案
//response.setHeader("Pragma", "");
//response.setHeader("Cache-Control", "");
//response.setHeader("Content-Disposition", "inline; filename=" + encodeFileName + ";"); //直接開啟檔案
response.setHeader("Content-Disposition","attachment; filename=" + encodeFileName + ";"); //另存新檔
InputStream is = null;
javax.servlet.ServletOutputStream out = null;
try {
is = new ByteArrayInputStream(destFiles);
out = response.getOutputStream();
byte buffer[] = new byte[4096];
response.flushBuffer();
for(int n = 0; -1 != (n = is.read(buffer));){
out.write(buffer, 0, n);
}
} finally {
is.close();
}
}
%><% // --------不能有空行
String type = request.getParameter("type");
if ("1".equals(type)) {
String url = URLDecoder.decode(request.getParameter("url"),"UTF-8");
if (url != null && !"".equals(url)) {
String name = URLDecoder.decode(request.getParameter("name"),"UTF-8");
byte[] file = getFile2(url);
if (file != null) {
print(name, response, file);
}
}
} else {
java.util.List files = getFileList("smb://账号:密码@主机名或IP/Temp/");
if (files != null) {
out.println("<table border='1'>");
Map data = null;
for (int i = 0; i < files.size(); i++) {
data = (Map) files.get(i);
out.println("<tr><td><a target='dataframe' href='"
+ request.getContextPath()
+ "/smb.jsp?type=1&url="
+ data.get("recordurlall") + "&name="
+ data.get("name") + "'>" + URLDecoder.decode((String)data.get("name"),"UTF-8")
+ "</a><td></tr>");
}
out.println("</table>");
out.println("<iframe name='dataframe' width='0' height='0'></iframe>");
}
}
%>
3. 效果如下图:
注意: 为了保证下载文件不损坏,在JSP中的<%...%><%...%>之间不能有任何换行或空白,否则就会出现多出了些空行从而导致源文件损坏,当然如果用Servlet或 Struts等Java端实现就不会存在这样的问题……