package com.epipe.plm.cs.fm.serv;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.MalformedURLException;import java.net.URLEncoder;import java.net.UnknownHostException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import jcifs.smb.SmbException;import jcifs.smb.SmbFile;import jcifs.smb.SmbFileInputStream;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.tools.zip.ZipEntry;import org.apache.tools.zip.ZipOutputStream;import com.epipe.plm.common.ntko.NtkoBigFileUtils;import com.rh.core.base.Bean;import com.rh.core.base.Context;import com.rh.core.comm.FileServ;import com.rh.core.comm.FileStorage;import com.rh.core.serv.OutBean;import com.rh.core.serv.ParamBean;import com.rh.core.serv.ServDao;import com.rh.core.util.JsonUtils;import com.rh.core.util.RequestUtils;import common.Logger;/** * 初设文件管理后台类 * * @author LuJinming * */public class CsFmFileServ extends NtkoBigFileUtils { public static final Log log = LogFactory.getLog(CsFmFileServ.class); private static final int BUFFER_SIZE = 16 * 1024; // 创建文件夹 File createDir(String path) { log.error("DDDD:创建目录--" + path); File dirFile = null; try { dirFile = new File(path); if (!(dirFile.exists()) && !(dirFile.isDirectory())) { dirFile.mkdirs(); } } catch (Exception e) { e.printStackTrace(); } return dirFile; }; // 删除文件及文件夹 boolean delDir(File folder) { boolean result = false; try { String childs[] = folder.list(); if (childs == null || childs.length <= 0) { if (folder.delete()) { result = true; } } else { for (int i = 0; i < childs.length; i++) { String childName = childs[i]; String childPath = folder.getPath() + File.separator + childName; File filePath = new File(childPath); if (filePath.exists() && filePath.isFile()) { if (filePath.delete()) { result = true; } else { result = false; break; } } else if (filePath.exists() && filePath.isDirectory()) { if (delDir(filePath)) { result = true; } else { result = false; break; } } } } folder.delete(); } catch (Exception e) { e.printStackTrace(); result = false; } return result; } /** * 压缩文件夹 * * @param filepath * @param zippath * @param dirFlag */ void zipMultiFile(String filepath, String zippath) { try { File file = new File(filepath);// 要被压缩的文件夹 File zipFile = new File(zippath); ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream( zipFile)); if (file.isDirectory()) { File[] files = file.listFiles(); for (File fileSec : files) { log.error("文件名字1:"+ fileSec.getName()); recursionZip(zipOut, fileSec); log.error("文件名字2:"+ fileSec.getName()); } } zipOut.close(); } catch (Exception e) { e.printStackTrace(); } // 删除临时文件 deleteFiles(new File(filepath)); } /** * 删除文件和文件夹 * * @param f */ void deleteFiles(File f) { // 如果是文件,直接删除 if (f.isFile()) { f.delete(); return; } // 如果是文件夹,先遍历删除里面的文件,最后在把本文件夹删除 File[] fs = f.listFiles(); for (File file : fs) { // 递归调用的目的是,文件夹里可能有子文件夹 deleteFiles(file); } // 删除文件夹 f.delete(); } /** * 递归获取文件 * * @param zipOut * @param file * @param baseDir * @throws Exception */ void recursionZip(ZipOutputStream zipOut, File file) throws Exception { byte[] buf = new byte[1024]; InputStream input = new FileInputStream(file); zipOut.putNextEntry(new ZipEntry(file.getName())); int len; zipOut.setEncoding("gbk");// 解决中文乱码问题 while ((len = input.read(buf)) != -1) { zipOut.write(buf, 0, len); } input.close(); } /** * 压缩文件 * * @param out * @param inputFolder * @param base */ void zipFile(ZipOutputStream out, File inputFolder, String base) { FileInputStream in = null; try { if (inputFolder.isDirectory()) { File[] fl = inputFolder.listFiles(); out.putNextEntry(new ZipEntry(base + "/")); base = base.length() == 0 ? "" : base + "/"; for (int i = 0; i < fl.length; i++) { zipFile(out, fl[i], base + fl[i].getName()); } } else { out.putNextEntry(new ZipEntry(base)); in = new FileInputStream(inputFolder); int b; while ((b = in.read()) != -1) { out.write(b); } out.setEncoding("gbk");// 解决中文乱码问题 in.close(); } } catch (Exception e) { try { in.close(); } catch (IOException e1) { e1.printStackTrace(); } e.printStackTrace(); } } /** * 用于下载路径为绝对路径的文件,下载地址为downLoadPath * * @param filePath * @param downLoadPath * @throws Exception */ void downLocalFile(String filePath, String downLoadPath) throws Exception { File file = new File(filePath); FileInputStream fis = new FileInputStream(file); BufferedInputStream buff = new BufferedInputStream(fis); byte[] b = new byte[1024];// 相当于我们的缓存 long k = 0;// 该值用于计算当前实际下载了多少字节 // 从response对象中得到输出流,准备下载 OutputStream myout = new FileOutputStream(downLoadPath); // 开始循环下载 while (k < file.length()) { int j = buff.read(b, 0, 1024); k += j; // 将b中的数据写到客户端的内存 myout.write(b, 0, j); } fis.close(); myout.close(); buff.close(); } /** * 根据fileId读取上传模板,写到临时文件内 * * @param fileId * @param inputFolderName */ void readAndWriteFile(String fileId, String inputFolderName) { log.error("DDD: 下载文件--" + inputFolderName); Bean resultBean = ServDao.find("NTKOBIGFILEINFO", fileId); FileOutputStream fileOut = null; InputStream is = null; try { String filePath = resultBean.getStr("FILE_PATH") + resultBean.getStr("FILE_NAME"); is = getInputStream(filePath); fileOut = new FileOutputStream(inputFolderName); byte[] buffer = new byte[BUFFER_SIZE]; int buffLen = is.read(buffer); while (buffLen != -1) { fileOut.write(buffer, 0, buffLen); buffLen = is.read(buffer); } } catch (Exception e) { e.printStackTrace(); } finally { try { fileOut.flush(); fileOut.close(); is.close(); } catch (Exception e2) { e2.printStackTrace(); } } } /** * 获取输入流 * * @param absolutePath * @return * @throws IOException */ public InputStream getInputStream(String absolutePath) { if (absolutePath.startsWith("smb://")) { // get from windows share file system SmbFileInputStream in = null; try { in = new SmbFileInputStream(absolutePath); } catch (SmbException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } return in; } else { // get from local file system FileInputStream in2 = null; File file = new File(absolutePath); try { in2 = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } return in2; } } /** * 下载前检查文件是否存在 * * @param param * @return */ public OutBean selectFile(ParamBean param) { String dataId = param.getStr("pkArrys"); String[] dataIdArr = dataId.split(","); String catalogId = param.getStr("parentId"); OutBean outbean = new OutBean(); // 选择文件时 if (catalogId == null || catalogId.equals("") || (!catalogId.equals("") && !dataIdArr[0].equals(""))) { String dataIdArrayList = "('" + dataId.replaceAll(",", "','") + "')"; String sql = "select FILEMD5_ID from NTKO_BIG_FILE_INFO where FILEMD5_ID in(select FILEMD5_ID from CS_FM_CSFILE where id in" + dataIdArrayList + ")"; int fileCount = Context.getExecutor().count(sql); if (fileCount < dataIdArr.length) { outbean.set("STATUS", "no"); } } else { // 选择目录时 String sql = "select C.FILEMD5_ID from CS_FM_CSFILE C , CS_FM_CATALOG G where C.FILE_CATALOG_ID = G.ID AND C.FILE_CATALOG_ID ='" + catalogId + "' and FILEMD5_ID not in (select FILEMD5_ID from ntko_big_file_info where project_catalogid='" + catalogId + "')"; int fileCount = Context.getExecutor().count(sql); if (fileCount > 0) { outbean.set("STATUS", "no"); } } return outbean; } /** * 下载选定目录下的文件 * * @param param * @throws Exception */ public void downloadCatalogFile(ParamBean param) throws Exception { log.error("DDDD:开始"); HttpServletResponse response = Context.getResponse(); HttpServletRequest request = Context.getRequest(); String systemFilePath = Context.getSyConf("NTKO_FILE_ROOT_PATH", "") + File.separator + "download"; // 临时文件路径 String paramStr = param.getStr("param"); Bean paramBean = JsonUtils.toBean(paramStr); String dataId = paramBean.getStr("pkArrys"); String[] dataIdArr = dataId.split(","); String catalogId = paramBean.getStr("parentId"); String calalogname = paramBean.getStr("CATALOG_NAME"); response.setContentType("application/x-zip-compressed;charset=GBK"); response.setCharacterEncoding("gbk"); // 根据根目录遍历全部的文件 ListcatalogList = new ArrayList ();// 目录及子目录 List fileList = new ArrayList ();// 目录及子目录下全部文件 String queryRootBean = "select * from CS_FM_CATALOG where ID = '" + catalogId + "'"; Bean rootBean = Context.getExecutor().queryOne(queryRootBean); String fileId = null; String fileName = null; log.error("DDDD:dataId--" + dataId); // 有选择目录的 if (rootBean != null) { // 既选择目录又选择文件时 if (dataIdArr.length > 0 && !dataIdArr[0].equals("")) { System.out.println(dataIdArr.length); System.out.println(dataIdArr[0]); String dataIdArrayList = "('" + dataId.replaceAll(",", "','") + "')"; String sql = " SELECT FILEMD5_ID,FILE_ORIGINALE_NAME,FILE_PATH,FILE_NAME FROM NTKO_BIG_FILE_INFO WHERE FILEMD5_ID in ( select FILEMD5_ID from CS_FM_CSFILE WHERE ID in " + dataIdArrayList + " )"; fileList = Context.getExecutor().query(sql); } else { // 选择目录但不选择文件 StringBuffer path = new StringBuffer(""); findFile(rootBean, catalogList, fileList, path, "download"); } String savePath = null; for (Bean name : fileList) { fileId = name.getStr("FILEMD5_ID"); fileName = name.getStr("FILE_ORIGINALE_NAME"); savePath = calalogname; String filePath = name.getStr("FILE_PATH"); String fileMd5Name = name.getStr("FILE_NAME"); // 将文件存入临时文件夹中 if (filePath.indexOf(":/") != -1 || filePath.substring(0, 1).equals("\\\\")) { createDir((systemFilePath + File.separator + savePath) .replaceAll("\\\\", "/")); downLocalFile(filePath +"/"+ fileMd5Name, (systemFilePath + File.separator + savePath + File.separator + fileName).replaceAll( "\\\\", "/")); } else { savePath = (systemFilePath + File.separator + savePath + File.separator) .replaceAll("\\\\", "/"); createDir(savePath); readAndWriteFile(fileId, savePath + fileName); } } if (!dataIdArr[0].equals("") && dataIdArr.length == 1) { RequestUtils.setDownFileName(request, response, fileName); } else { RequestUtils.setDownFileName(request, response, calalogname + ".zip"); } } else { // 不选目录,选择单个文件下载 if (dataIdArr.length == 1) { String sql = "SELECT FILEMD5_ID,FILE_ORIGINALE_NAME FROM NTKO_BIG_FILE_INFO WHERE FILEMD5_ID in ( select FILEMD5_ID from CS_FM_CSFILE WHERE ID ='" + dataIdArr[0] + "')"; List result = Context.getExecutor().query(sql); fileId = result.get(0).getStr("FILEMD5_ID"); fileName = result.get(0).getStr("FILE_ORIGINALE_NAME"); // 不选目录只选单个文件时,压缩包名=文件名 calalogname = fileName.substring(0, fileName.indexOf(".")); RequestUtils.setDownFileName(request, response, fileName); Bean fileBean = ServDao.find("NTKOBIGFILEINFO", fileId);// 通过fileid // 来获取file的Bean对象 InputStream input = getInputStream(fileBean.getStr("FILE_PATH") + fileBean.getStr("FILE_NAME"));// 将文件的Bean对象转换为流对象 createDir(systemFilePath + "/" + calalogname); FileOutputStream fileOut = new FileOutputStream(systemFilePath + "/" + calalogname + "/" + fileName); byte[] buffer = new byte[BUFFER_SIZE]; int buffLen; while ((buffLen = input.read(buffer)) != -1) { fileOut.write(buffer, 0, buffLen); buffLen = input.read(buffer); } fileOut.flush(); fileOut.close(); input.close(); } else { // 不选目录,选择多个文件下载 String dataIdArrayList = "('" + dataId.replaceAll(",", "','") + "')"; String sql = "SELECT FILEMD5_ID,FILE_ORIGINALE_NAME,FILE_NAME FROM NTKO_BIG_FILE_INFO WHERE FILEMD5_ID in ( select FILEMD5_ID from CS_FM_CSFILE WHERE ID in " + dataIdArrayList + " )"; fileList = Context.getExecutor().query(sql); createDir(systemFilePath);// 创建文件夹 String sqlp = "SELECT P.NAME name FROM PROJECT_CONFIG_PROJECT P,CS_FM_CSFILE F WHERE P.ID = F.PROJECT_ID AND F.ID in " + dataIdArrayList + " "; Bean projectNmae = Context.getExecutor().queryOne(sqlp); RequestUtils.setDownFileName(request, response, projectNmae.getStr("NAME") + ".zip"); // 不选目录选多个文件时,压缩包名为项目名 calalogname = projectNmae.getStr("NAME"); for (Bean name : fileList) { fileId = name.getStr("FILEMD5_ID"); fileName = name.getStr("FILE_ORIGINALE_NAME");// Bean fileBean = ServDao.find("NTKOBIGFILEINFO", fileId);// String filePath = fileBean.getStr("FILE_PATH");// String filemd5Name = name.getStr("FILE_NAME"); // 将文件存入临时文件夹中// if (filePath.indexOf(":/") != -1// || filePath.substring(0, 1).equals("/")) {// downLocalFile(filePath+ "/" + filemd5Name, systemFilePath + "/" + fileName);// } else {// createDir(systemFilePath + "/"// + projectNmae.get("NAME") + "/");// readAndWriteFile(fileId, systemFilePath + "/"// + projectNmae.get("NAME") + "/" + fileName);// } String savePath = (systemFilePath + File.separator + projectNmae.get("NAME") + File.separator) .replaceAll("\\\\", "/"); createDir(savePath); readAndWriteFile(fileId, savePath + fileName); } } } log.error("DDD: 开始压缩"); // ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());// File inputFolder = new File(systemFilePath);//// try {//// zipFile(zipOut, inputFolder, "");// } catch (Exception e) {// e.printStackTrace();// }// zipOut.flush();// zipOut.close();// delDir(inputFolder); javax.servlet.ServletOutputStream outPutStream = response.getOutputStream(); InputStream is = null; String path=systemFilePath + "/" + calalogname+".zip"; File file=new File(path); try { // 压缩文件 zipMultiFile(systemFilePath + "/" + calalogname, path); is = new FileInputStream(file); byte[] content = new byte[1024]; int length = 0; while ((length = is.read(content)) != -1) { outPutStream.write(content, 0, length); } outPutStream.flush(); } catch (Exception e) { System.out.println("sd"); e.printStackTrace(); } finally { outPutStream.close(); is.close(); delDir(file);// 临时文件删除 log.error("DDD: 下载完成,临时文件删除"); } } /** * 通过递归查找所有的目录、文件 modify:2016-7-29 新增逻辑,关于删除的处理 若目录下有文件,则该目录及其相关的父目录都不能删除 * * @param catalogId * 所需查找的目录ID * @param catalogList * 用于存放递归查询出的全部的目录 * @param fileList * 用于存放递归查询出的全部的文件 * @param path * 上一层级的目录结构 */ public boolean findFile(Bean rootBean, List catalogList, List fileList, StringBuffer path, String type) { boolean flag = true; // 用于标识本机目录是否可以删除,true为可以删除,false为不可删除 boolean result = true;// 用于记录遍历返回结果 StringBuffer nowPath = new StringBuffer(path.toString()); nowPath.append(File.separator + rootBean.getStr("CATALOG_NAME"));// 当前层级目录结构 // 1.判断该目录id下是否有子目录 StringBuffer queryChildNode = new StringBuffer( "select ID,CATALOG_DISPLAY,CATALOG_NAME from CS_FM_CATALOG"); queryChildNode.append(" where PARENT_ID = '"); queryChildNode.append(rootBean.getStr("ID")); queryChildNode.append("'"); List childList = Context.getExecutor().query( queryChildNode.toString()); // --- 有子目录:对全部的子目录进行递归 if (childList != null && childList.size() > 0) { for (Bean child : childList) { if (!findFile(child, catalogList, fileList, nowPath, type)) { result = false; } } } // 2. 根据目录Id:查找文件,对该目录下文件进行操作 StringBuffer queryFile = new StringBuffer( "select c.ID ID,s.FILE_ORIGINALE_NAME FILE_ORIGINALE_NAME,s.FILEMD5_ID FILEMD5_ID ,s.FILE_PATH FILE_PATH,s.FILE_NAME FILE_NAME from CS_FM_CSFILE c,NTKO_BIG_FILE_INFO s where c.FILEMD5_ID = s.FILEMD5_ID and c.FILE_CATALOG_ID ='"); queryFile.append(rootBean.getStr("ID")); queryFile.append("'"); if (type.equals("delete")) { queryFile.append(" AND (c.FILE_STATE = '1' or c.FILE_STATE='4')"); } List fileResultList = Context.getExecutor().query( queryFile.toString()); if (fileResultList != null && fileResultList.size() > 0) { for (Bean fileBean : fileResultList) { fileBean.set("CATLOG_PATH", nowPath.toString());// 设置该文件的路径结构 fileList.add(fileBean);// 将文件的Bean存入用于存放全部文件的list(fileList) } } // 根据下层递归来的结果,判断是否将目录加入遍历结果 if (result && flag) {// 实际只有删除的时候result会变为false catalogList.add(rootBean); } return flag; } /** * 文件删除按钮相关后台操作 已上传和已通过的文件不进行删除 * * @author LuJinming */ public void deleteFile(ParamBean paramBean) { String ids = paramBean.getStr("IDS");// 数据主键,多条数据使用逗号隔开 ids = ids.replaceAll(",", "','");// 转换为查询语句中的格式 // 查询出需要删除的数据 StringBuffer queryData = new StringBuffer( "select * from CS_FM_CSFILE where ID in ('"); queryData.append(ids); queryData.append("') "); List dataResult = Context.getExecutor().query( queryData.toString()); if (dataResult != null && dataResult.size() > 0) { // 删除CS_FM_CSFILE中的数据 StringBuffer deleteFileData = new StringBuffer( "delete CS_FM_CSFILE where ID in ('"); deleteFileData.append(ids); deleteFileData.append("')"); Context.getExecutor().execute(deleteFileData.toString()); } } /** * 根据ID进行删除 1. 删除数据下挂载的文件实际文件 2. 删除该条数据(或多条数据) * * @param ids * 传入数据格式 xxx,xxx,xxx,xxx */ public void deleteById(String ids) { } // 根据路径删除文件方法 public boolean deleteFile(String filePath) { boolean flag = true;// 标记删除是否成功 if (filePath.contains("smb://")) {// 如果路径是smba协议的 try { SmbFile smbFile = new SmbFile(filePath); if (smbFile.isFile() && smbFile.exists()) { smbFile.delete(); } else { flag = false; } } catch (Exception e) { e.printStackTrace(); flag = false; } } else { File file = new File(filePath); if (file.isFile() && file.exists()) { file.delete(); } else { flag = false; } } return flag; } /** * 目录删除相关后台方法 * * 2016-6-29 逻辑修改 逻辑更改为,遍历当前的目录,获取全部的目录、文件,全部删除 * */ public OutBean deleteCatalog(ParamBean paramBean) { StringBuffer msg = new StringBuffer(); String catalogId = paramBean.getStr("CATALOG_ID");// 目录ID List catalogList = new ArrayList ();// 目录及子目录 List fileList = new ArrayList ();// 目录及子目录下全部文件 String queryRootBean = "select * from CS_FM_CATALOG where ID = '" + catalogId + "'"; Bean rootBean = Context.getExecutor().queryOne(queryRootBean); StringBuffer path = new StringBuffer(""); findFile(rootBean, catalogList, fileList, path, "delete"); if (fileList != null && fileList.size() > 0) { for (Bean bean : fileList) { // 删除文件 String MD5ID = bean.getStr("FILEMD5_ID"); Bean resultBean = ServDao.find("NTKOBIGFILEINFO", MD5ID); deleteFileCS(resultBean); StringBuffer deleteSyData = new StringBuffer( "delete NTKO_BIG_FILE_INFO where FILEMD5_ID = '"); deleteSyData.append(MD5ID); deleteSyData.append("'"); // 删除系统表中的数据 Context.getExecutor().execute(deleteSyData.toString()); // 删除在CS_FM_CSFILE StringBuffer deleteFileData = new StringBuffer( "delete CS_FM_CSFILE where ID = '"); deleteFileData.append(bean.getStr("ID")); deleteFileData.append("'"); Context.getExecutor().execute(deleteFileData.toString()); } } // 删除目录 if (catalogList != null && catalogList.size() > 0) { for (Bean catalogBean : catalogList) { String id = catalogBean.getStr("ID"); StringBuffer deleteCatalog = new StringBuffer( "delete CS_FM_CATALOG where ID ='"); deleteCatalog.append(id); deleteCatalog.append("' and CATALOG_TYPE != '1'"); Context.getExecutor().execute(deleteCatalog.toString()); } } msg.append("OK");// 删除成功 return new OutBean().set("msg", msg.toString()); } /** * 删除文件 (db & fs) * * @param file * - file bean * @return deletes result */ public static boolean deleteFileCS(Bean file) { boolean result = false; try { // 删除源文件 String absolutePath = file.getStr("FILE_PATH") + file.getStr("FILE_NAME"); FileStorage.deleteFile(absolutePath); // 删除相关文件,(如果存在) String relatedPath = buildRelatedPathExpress( file.getStr("FILE_PATH"), ""); boolean exits = FileStorage.exists(relatedPath); if (exits) { FileStorage.deleteDirectory(relatedPath); } result = true; } catch (IOException e) { LogFactory.getLog(FileServ.class).warn( "delete file failed from disk.", e); result = false; } return result; } /** * 生成相关文件的路径表达式 * * @param fileExpre * - 源文件路径表达式 * @param relatedFile * - 相关文件名 * @return relatedPathExpress */ private static String buildRelatedPathExpress(String fileExpre, String relatedFile) { String targetExpre = fileExpre + "_file/" + relatedFile; return targetExpre; } /** * 更改文件状态相关后台方法 1.上报 将文件状态由 已上传 改为 已上报 2.确认通过 将文件状态由 已上报改为 审批通过 3.确认退回 * 将文件状态由 已上报改为 审批不通过 */ public void changeState(ParamBean paramBean) { String ids = paramBean.getStr("IDS"); String state = paramBean.getStr("STATE");// 文件状态 ids = ids.replaceAll(",", "','");// 需要更改状态的数据 Date date = new Date(); SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd"); String now = fm.format(date); StringBuffer updateSql = new StringBuffer( "update CS_FM_CSFILE set FILE_STATE = '"); updateSql.append(state); updateSql.append("'"); if (state.equals("2")) {// 更新上报人和上报时间 updateSql.append(" ,REPORTER ='"); updateSql.append(Context.getUserBean().getId()); updateSql.append("',REPORT_TIME ='"); updateSql.append(now); updateSql.append("' "); } else if (state.equals("3") || state.equals("4")) {// 更新确认人和确认时间 updateSql.append(" ,CONFIRMER ='"); updateSql.append(Context.getUserBean().getId()); updateSql.append("',CONFIRM_TIME ='"); updateSql.append(now); updateSql.append("' "); } updateSql.append(" where ID in('"); updateSql.append(ids); updateSql.append("')"); Context.getExecutor().execute(updateSql.toString()); }}