檔案上傳---檔案解壓---讀取檔案---檔案重新命名壓縮
阿新 • • 發佈:2019-01-02
JAVA開發web專案 程式碼的順序是按照程式碼執行的順序寫的,以下寫的是沒有傳遞id情況下,即是新增檔案情況
jsp頁面用uploadify外掛實現檔案上傳
//觸發上傳外掛的html頁面程式碼 <span class="chooseNodeSmall" onclick="fileUpload('')" style="margin-left:10px">檔案上傳</span> <!-- 上傳開始 上傳彈出框 --> <div id="fileUpload" style=" display: none; position: absolute; left: 20%; top: 30%;width:450px;height:170px;overflow:hidden;border:3px solid #98999D;padding:12px;border-radius:10px;z-index:10;background-color:white"> <br> <div style="height:130px"> <input id="uploadify" type="file" name="uploadify"/> <input type="hidden" name="id" id="updateDocId"/> <span onclick="closeFileUploadWindow()" style="position:absolute;left:420px;top:10px" class="uploadType">關閉</span> </div> <div style="height:30px" > <a href="javascript:$('#uploadify').uploadify('upload','*')" class="uploadType">開始上傳</a> <a href="javascript:$('#uploadify').uploadify('cancel')" class="uploadType">取消上傳</a> </div> </div> <div id="mask" style="display:none"></div>//用於顯示彈出框下層的陰影
css程式碼
js程式碼<style type="text/css"> .chooseNodeSmall{ cursor:pointer; background-color:#7F99BE; border:1px solid #D3D3D3; padding:4px 7px; color:white; font-weight:bold; font-size:13px; margin-left:30px; } #mask{ width: 100%; height: 200%; position: absolute; background-color: #000; left: 0; opacity:0.5; top: 0; z-index: 8; } </style>
function fileUpload(id){
$("#mask").show();
$("#fileUpload").css("display","block");
$("#updateDocId").val(id);
}
function closeFileUploadWindow(){
$("#mask").hide();
$("#fileUpload").css("display","none");
}
uploadify外掛js程式碼實現
$(function(){ $("#uploadify").uploadify({ 'swf' : "${pageContext.request.contextPath}/static/js/uploadify/uploadify.swf", 'uploader' : "${pageContext.request.contextPath}/document/uploadFile",//檔案上傳地址 'queueId' : "fileQueue", 'queueSizeLimit' : 1,//限制上傳檔案的數量 'fileExt' : "*.rar,*.zip",//'fileDesc' : "RAR *.rar",//限制檔案型別 'fileTypeDesc' : '壓縮檔案', //可選擇檔案型別說明 'auto' : false, //是否直接上傳,若為true則不用點選開始上傳 'multi' : true,//是否允許多檔案上傳 'method' :'post', 'width' : '65', //按鈕寬度 'height' : '18', //按鈕高度 'simUploadLimit': 2,//同時執行上傳的程序數量 'scriptData': { "id": $("#updateDocId").val()},//傳遞其它的引數-----#*************** 'buttonText': "選擇檔案", 'fileObjName' : 'uploadFile', 'onFallback':function(){ alert("您未安裝FLASH控制元件,無法上傳圖片!請安裝FLASH控制元件後再試。"); }, 'onUploadStart' : function(file) { $("#uploadify").uploadify("settings", "formData", {'id' : $("#updateDocId").val()}); <span style="font-family: Arial, Helvetica, sans-serif;">//傳遞其它的引數(檔案ID值,若有則為更新檔案)----#***************</span> }, 'onUploadSuccess' : function(file, data, response){//單個檔案上傳成功觸發 var json = eval('(' + data + ')'); //解析成JSON格式 if(json.flag){ flag += 1; $.messager.alert("info",json.msg,"success"); $('#uploadify').uploadify('cancel'); closeFileUploadWindow(); }else{ $.messager.alert("info",json.msg,"error"); } }, }); })
本專案用的是spring+springmvc+jpa開發框架
controller層程式碼
/**
* 新增檔案或更新檔案,根據有沒有傳檔案ID值來區分
* @return
*/
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ResponseEntity<?> uploadFile(@RequestParam("uploadFile") CommonsMultipartFile file,HttpServletResponse response,HttpServletRequest request) {
//文件更新與新增的公共程式碼
Map<String, String> map = new HashMap<String, String>();
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if(split.length >2){
map.put("msg", "壓縮檔案命名不規範,只能存在一個點");
return new ResponseEntity<Map<String, String>>(map, HttpStatus.OK);
}
File newFile = new File(PropsUtil.getProperty("document.FirstPath")+File.separatorChar+fileName);
if(!new File(PropsUtil.getProperty("document.FirstPath")).exists()){
new File(PropsUtil.getProperty("document.FirstPath")).mkdirs();
}
if(StringUtils.equals(split[1],"zip")){
if(split[0].length() < 50 && StringUtils.isNotBlank(split[0])){
String param_id = request.getParameter("id");
if(StringUtils.isNotBlank(param_id)){
//此時為更新
//首先將該ID的檔案全部刪除
FileUtil.delete(new File(PropsUtil.getProperty("document.actualPath") + param_id +".zip"));
FileUtil.deltree(new File(PropsUtil.getProperty("document.actualIconPath") + param_id ));
try {
file.transferTo(newFile);
Map<String, String> analyzeResult = analyzeFile(PropsUtil.getProperty("document.FirstPath")+File.separatorChar + fileName,param_id,split[0]);
System.out.println("analyzeResult-------------------------------"+analyzeResult.toString());
Document document = new Document();
document.setId(param_id);
//查詢該記錄的版本號,在些基礎上加1
int oldVersion = documentService.getOldVersionById(param_id);
document.setDocument_version(++oldVersion);
if(!analyzeResult.containsKey("msg")){
map = saveDocInfo(map, split, document, analyzeResult);
System.out.println("map-------------------------------"+map.toString());
if(map.containsKey("flag")){
map.put("msg", "檔案更新成功");
}
}else{
map.put("msg", analyzeResult.get("msg"));
}
return new ResponseEntity<Map<String, String>>(map, HttpStatus.OK);
} catch (IllegalStateException | IOException e) {
logger.error("資料uploadFile異常:", e);
//刪除原檔案
FileUtil.delete(new File(PropsUtil.getProperty("document.FirstPath")+File.separatorChar+fileName));
throw new RestException(messageSourceHelper.getMessage(e.getMessage()));
}
}else{
//此時為新增新檔案
try {
//儲存檔案資訊,使最後的修改的檔名為記錄的id,這步很重要
Document doc = documentService.saveDoc(split[0]);
file.transferTo(newFile);
Map<String, String> analyzeResult = analyzeFile(PropsUtil.getProperty("document.FirstPath")+File.separatorChar + fileName,doc.getId(),split[0]);
System.out.println("analyzeResult-------------------------------"+analyzeResult.toString());
if(!analyzeResult.containsKey("msg")){
map = saveDocInfo(map, split, doc, analyzeResult);
System.out.println("map-------------------------------"+map.toString());
}else{
map.put("msg", analyzeResult.get("msg"));
}
return new ResponseEntity<Map<String, String>>(map, HttpStatus.OK);
} catch (Exception e) {
logger.error("資料uploadFile異常:", e);
//刪除原檔案
FileUtil.delete(new File(PropsUtil.getProperty("document.FirstPath")+File.separatorChar+fileName));
throw new RestException(messageSourceHelper.getMessage(e.getMessage()));
}
}
}else{
map.put("msg", "上傳壓縮檔名不能超過50個字元");
}
}else{
map.put("msg", "請選擇zip檔案上傳");
}
return null;
}
匯入ant.jar包,import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile;用util.zip的包會報錯,
/**
*
* @param filePath 需要解析的檔案路徑(zip檔案)
* @param id 檔案的新名稱,若不想改名,可傳原檔名
* @param fileName2 解析的檔名
* @return
*/
private Map<String, String> analyzeFile(String filePath, String id, String fileName2) {
Map<String, String> map = new HashMap<String, String>();
//將檔案解壓縮----------start
ZipFile zipFile;
try {
zipFile = new ZipFile(filePath);
Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.getEntries();
while (enu.hasMoreElements()) {
ZipEntry zipElement = (ZipEntry) enu.nextElement();// 單個檔案 物件
InputStream read = zipFile.getInputStream(zipElement); // 單個檔案檔案的流
String fileName = zipElement.getName(); // 單個檔名字
String outPath = (PropsUtil.getProperty("document.unzipPath")+ File.separator + fileName).replaceAll("\\*", "/");
// 判斷路徑是否存在,不存在則建立檔案路徑
File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
if (!file.exists()) {
file.mkdirs();
}
// 判斷檔案全路徑是否為資料夾,如果是,不需要解壓
if (new File(outPath).isDirectory()) {
continue;
}
OutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[1024];
int len;
//將zipFileT中的檔案複製到uploadFile資料夾中
while ((len = read.read(buf1)) > 0) {
out.write(buf1, 0, len);
}
read.close();
out.close();
}
zipFile.close();
//將檔案解壓縮----------end
//刪除原檔案
FileUtil.delete(filePath);
//讀取config.json到MAP中(config.json是上傳檔案的配置檔案,業務需求,要讀取裡面的內容儲存到資料庫)
map = readConfigMsgToMap(fileName2);
//檔案標題不能重複,若重複提示報錯
Boolean flag = documentService.findRepeatTitle(map.get("title"));
if(flag){
//此時說明資料庫中已經存在相同的標題,
//刪除解壓資料夾
FileUtil.deltree(new File(PropsUtil.getProperty("document.unzipPath")+ File.separator + fileName2));
//刪除該條記錄
documentService.delete(id);
map.put("msg", "上傳檔案標題已存在,請修改壓縮檔案裡config.json檔案的title值");
return map;
}
//更改檔名,為後面壓縮檔案做準備
File f1 = new File(PropsUtil.getProperty("document.unzipPath")+ File.separator + fileName2);
File f2 = new File(PropsUtil.getProperty("document.unzipPath")+ File.separator + id);
boolean renameTo = f1.renameTo(f2);//這一步有時會報錯,那是因為流沒有關閉,一定要確保上面用到的流全部關閉
System.out.println("f1---"+f1+"renameTo ---f2"+f2+"---"+renameTo);
boolean fileToZip = fileToZip(PropsUtil.getProperty("document.unzipPath"), PropsUtil.getProperty("document.actualPath"), id);//將解壓後的檔案重新壓縮,重新命名********************
//將檔案的icon.png檔案複製到目標資料夾
FileUtil.copyFile(PropsUtil.getProperty("document.unzipPath")+ id+ File.separator + map.get("icon"), PropsUtil.getProperty("document.actualIconPath")+ id+ File.separator + "icon.png", true);//這步還沒有刪除之前解壓的檔案,取出圖片放到目標位置,備用
//如果壓縮檔案成功,將被壓縮的檔案刪除
if(fileToZip){
FileUtil.deltree(new File(PropsUtil.getProperty("document.unzipPath")+ File.separator + id));
}else{
//刪除解壓資料夾
FileUtil.deltree(new File(PropsUtil.getProperty("document.unzipPath")+ File.separator + fileName2));
map.put("msg", "檔案壓縮失敗");
}
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
下面是資料夾的壓縮,花費了很長時間才解決,有部分程式碼是轉別人的,但他的只能壓縮單個檔案,不能壓縮資料夾,在他的基礎上做了修改,實現了壓縮資料夾
/**
* 將存放在sourceFilePath目錄下的原始檔,打包成fileName名稱的zip檔案,並存放到zipFilePath路徑下
* @param sourceFilePath :待壓縮的檔案路徑
* @param zipFilePath :壓縮後存放路徑
* @param fileName :壓縮後文件的名稱
* @return
*/
public static boolean fileToZip(String sourceFilePath,String zipFilePath,String fileName){
boolean flag = false;
File sourceFile = new File(sourceFilePath);
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
if(sourceFile.exists() == false){
System.out.println("待壓縮的檔案目錄:"+sourceFilePath+"不存在.");
}else{
try {
File zipFile = new File(zipFilePath + "/" + fileName +".zip");
if(zipFile.exists()){
System.out.println(zipFilePath + "目錄下存在名字為:" + fileName +".zip" +"打包檔案.");
}else{
File file = new File(zipFilePath);
if (!file.exists()) {
file.mkdirs();
}
File[] sourceFiles = sourceFile.listFiles();
if(null == sourceFiles || sourceFiles.length<1){
System.out.println("待壓縮的檔案目錄:" + sourceFilePath + "裡面不存在檔案,無需壓縮.");
}else{
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(new BufferedOutputStream(fos));
byte[] bufs = new byte[1024*10];
for(int i=0;i<sourceFiles.length;i++){
//建立ZIP實體,並新增進壓縮包
ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());
//讀取待壓縮的檔案並寫進壓縮包裡
if(sourceFiles[i].isDirectory()){
//遞迴讀取檔案流中資料
parseFileToZip(sourceFiles[i],"", zos);//實現壓縮資料夾關鍵****************
}else{
zos.putNextEntry(zipEntry);
fis = new FileInputStream(sourceFiles[i]);
bis = new BufferedInputStream(fis, 1024*10);
int read = 0;
while((read=bis.read(bufs, 0, 1024*10)) != -1){
zos.write(bufs,0,read);
}
}
}
}
}
flag = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally{
//關閉流
try {
if(null != bis) bis.close();
if(null != zos) zos.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
return flag;
}
實現壓縮資料夾關鍵
/**
* @param file 輸入檔案
* @param oppositePath 檔案層級(必有,否則壓縮後的檔案沒有層級結構)
* @param zos2 輸出流
*/
private static void parseFileToZip(File file,String oppositePath, ZipOutputStream zos2) {
oppositePath = oppositePath +file.getName()+"/";
ZipEntry zipEntry = new ZipEntry(oppositePath);
try {
zos2.putNextEntry(zipEntry);
} catch (IOException e1) {
e1.printStackTrace();
}
FileInputStream fis = null;
BufferedInputStream bis = null;
File[] sf = file.listFiles();
for(int i=0;i<sf.length;i++){
if(sf[i].isDirectory()){
parseFileToZip(sf[i],oppositePath, zos2);
}else{
try {
ZipEntry zipEntryC = new ZipEntry(oppositePath + sf[i].getName());
zos2.putNextEntry(zipEntryC);
byte[] bufs = new byte[1024*10];
fis = new FileInputStream(sf[i]);
bis = new BufferedInputStream(fis, 1024*10);
int read = 0;
while((read=bis.read(bufs, 0, 1024*10)) != -1){
zos2.write(bufs,0,read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
//關閉流
try {
if(null != fis) fis.close();
if(null != bis) bis.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
}
ps:outputstream(輸出流必須到資料夾下重新命名的檔案,輸出目標檔案的所在的資料夾必須存在,沒有則要先建立,否則會報找一到檔案錯誤),inputstream(輸入流必須到檔案,否則會報錯)**************************
因為更新與新增都用到saveDocInfo,所以提出來了,這一步是將config.json讀出的資料儲存到資料庫中,當然是更新記錄,因為id已經存在了
/**
* @param map
* @param split
* @param doc
* @param analyzeResult
*/
private Map<String, String> saveDocInfo(Map<String, String> map, String[] split, Document doc, Map<String, String> analyzeResult) {
if(StringUtils.isNotBlank(analyzeResult.get("icon")) && StringUtils.isNotBlank(analyzeResult.get("path")) && StringUtils.isNotBlank(analyzeResult.get("title"))){
//檔案資訊儲存到資料庫
doc.setId(doc.getId());
doc.setDocument_icon(doc.getId() + File.separator +"icon.png");
doc.setDocument_page_count(Integer.parseInt(analyzeResult.get("pages")));
doc.setDocument_md5_sum(getMD5(new File(PropsUtil.getProperty("document.actualPath")+File.separatorChar + doc.getId()+".zip")));
doc.setDocument_name(split[0]);
doc.setDocument_summary(analyzeResult.get("describe"));
doc.setDocument_title(analyzeResult.get("title"));
doc.setUpdate_time(new Date());
doc.setDocument_is_new(0);
doc.setDocument_download_path("zipfiles/"+doc.getId()+".zip");
doc.setDocument_local_path(PropsUtil.getProperty("document.actualPath")+doc.getId()+".zip");
if(doc.getDocument_version()!=null){
doc.setDocument_version(doc.getDocument_version() +1);
}else{
doc.setDocument_version(1);
}
if(StringUtils.isNotBlank(analyzeResult.get("tags"))){
doc.setDocument_keywords(analyzeResult.get("tags"));
}
if(StringUtils.isNotBlank(analyzeResult.get("type"))){
doc.setDocument_type(analyzeResult.get("type"));
}
//獲取檔案大小
File filed = new File(PropsUtil.getProperty("document.actualPath")+ doc.getId()+".zip" );
if(filed.exists()){
doc.setDocument_size((int)filed.length());
}
documentService.saveEntity(doc);
if(!map.containsKey("msg")){
map.put("msg", "檔案上傳成功");
map.put("flag", "true");
}
}else{
map.put("msg", "請檢查上傳檔案完整性");
}
return map;
}
到此結束,程式碼主要都在controller層,其它層就不寫了