java io流文件操作是很基礎的東西,最近正好寫了一整套功能,上傳,在頁面顯示文件名、路徑、上層目錄,並提供下載,刪除功能,需求挺簡單,代碼也不復雜,在這裏提供一下,也算作個筆記。
1.文件上傳
前端代碼:無非就是一個表單提交,寫了個動態添加file標籤的方法,每個file標籤後面對應着下拉框,供選擇路徑使用,即一個文件對應一個路徑。注:如果要上傳多個文件,而且路徑唯一,那麼不需像下面這樣一個file標籤對應一個文件,而是可以在file標籤中加個multipart屬性,這樣file標籤裏就可以選擇多個文件了。
<form name="xx" action="<%=appRoots%>/require/saveFile.do" method="post" enctype="multipart/form-data" id="formId" class="pageForm required-validate" onsubmit="return iframeCallback(this, dialogAjaxDone1);">
<table id="tb" class="searchContent e-w100" style="border-collapse:separate; border-spacing:0px 13px;">
<tr>
<td>
File:
</td>
<td>
<input type="file" name="photo">
<span>子文件夾:</span><!-- <input type="text" name="subFolder"/> -->
<select name="subFolder">
<option value="">請選擇</option>
<option value="接口文檔">接口文檔</option>
<option value="上線腳本">上線腳本</option>
</select>
<input type="text" name="roleIds" value="${reqId }" readonly="readonly"/>
<button onclick="_del(this);">刪除</button>
</td>
</tr>
</table>
<br/><!-- onclick="_submit();" -->
<a height="650" width="850" class="button mr5" onclick="_submit();">
<span>上傳</span>
</a>
<a height="650" width="850" class="button mr5" onclick="_add();" >
<span>增加</span>
</a>
</form>
<script type="text/javascript">
function _add(){
var tb = document.getElementById("tb");
//寫入一行
var tr = tb.insertRow();
//寫入列
var td = tr.insertCell();
//寫入數據
td.innerHTML="File:";
//再聲明一個新的td
var td2 = tr.insertCell();
//寫入一個input
td2.innerHTML='<input type="file" name="photo"/><span>子文件夾:</span> <select name="subFolder"><option value="">請選擇</option><option value="接口文檔">接口文檔</option><option value="上線腳本">上線腳本</option></select><input type="text" name="roleIds" value="${reqId }" readonly="readonly"/><button onclick="_del(this);">刪除</button>';
}
function _del(btn){
var tr = btn.parentNode.parentNode;
//alert(tr.tagName);
//獲取tr在table中的下標
var index = tr.rowIndex;
//刪除
var tb = document.getElementById("tb");
tb.deleteRow(index);
}
function _submit(){
//遍歷所的有文件
var files = document.getElementsByName("photo");
if(files.length==0){
alert("沒有可以上傳的文件");
return false;
}
for(var i=0;i<files.length;i++){
if(files[i].value==""){
alert("第"+(i+1)+"個文件不能爲空");
return false;
}
}
$("#formId").submit();
}
</script>
後臺代碼
上傳的後臺代碼很簡單,就是接收file數組,循環寫入的方法,需要注意的是,文件操作需要加註解,有些在xml配置裏,有些寫在java類配置裏,這裏就不多闡述了。
//@RequestParam MultipartFile對象需要用這個註解
@RequestMapping("/saveFile")
@ResponseBody
public AjaxResult saveFile(ModelAndView mav,@RequestParam MultipartFile [] photo,@Param("reqId") String reqId,@Param("roleIds") String[] roleIds,@Param("subFolder") String [] subFolder) throws IllegalStateException, IOException{
boolean result=true;
//服務器路徑
StringBuffer sb = new StringBuffer();
sb.append(System.getProperty("user.dir")).append("/").append("productTool/").append("File/").append(reqId);
AjaxResult ar=new AjaxResult();
try {
if(photo!=null&&photo.length>0){
//循環獲取file數組中得文件
for(int i = 0;i<photo.length;i++){
MultipartFile file = photo[i];
//文件名全稱
String fullName=file.getOriginalFilename();
//文件名前綴
String fileName=fullName.substring(0, fullName.indexOf("."));
//文件名後綴/文件類型
String fileType=fullName.substring(fullName.indexOf(".")+1, fullName.length());
StringBuffer ss = new StringBuffer();
if(subFolder!=null&&subFolder.length>0){
ss.append(roleIds[i]+"/"+subFolder[i]);
}else {
ss.append(roleIds[i]);
}
//創建文件夾
getFolder(ss);
file.transferTo(new File(ss.toString()+"/"+fullName));
}
}
if(result){
ar= new AjaxResult("200", "上傳附件成功");
ar.setCallbackType("closeCurrent");
JSONObject json=new JSONObject();
json.put("reqId", reqId);
ar.setForwardUrl("/require/QueryGeReqMain.do?json="+json.toString());
}
} catch (Exception e)
{
result=false;
ar=new AjaxResult("300", "上傳附件失敗");
}
return ar;
}
//創建多層文件夾
public static void getFolder(StringBuffer sb)
{
String[] dstfolders= sb.toString().split("/");
String[] paths=new String[dstfolders.length];
for(int i=0;i<dstfolders.length;i++){
String previous="";
if(i!=0){
previous=paths[i-1];
paths[i]=previous+"/"+dstfolders[i];
}else{
paths[i]=dstfolders[i];
}
}
for(int i=0;i<paths.length;i++){
File folder =new File(paths[i]);
if (!folder.exists() && !folder .isDirectory()){
folder.mkdir();
}
}
}
2.文件下載
前端代碼:
在轉發到這個頁面之前,已經通過方法將目標目錄下所有文件,包括子文件夾裏的文件查了出來,顯示在頁面上,每個文件後面配一個下載按鈕。
<div style=" overflow:scroll; width:100%; height:100%;">
<form name="xx" action="<%=appRoots%>/require/ddFile.do" method="post" id="formId" class="pageForm required-validate" onsubmit="return iframeCallback(this, dialogAjaxDone1);">
<p>
<label >需求編號:</label>
<input type="text" readonly="readonly" value="${reqId}" class="e-w212" />
</p>
<p>
<label >需求名稱:</label>
<input type="text" readonly="readonly" value="${reqName}" class="e-w212" />
</p>
<table class="e-w100 table" id="tbs">
<thead>
<tr>
<td style="width: 40%">
<div class="gridCol tl" title="文件名稱">文件名稱</div>
</td>
<td style="width: 30%">
<div class="gridCol tl" title="子文件夾">子文件夾</div>
</td>
<td style="width: 30%">
<div class="gridCol tl" title="操作">操作</div>
</td>
</tr>
</thead>
<tbody>
<c:forEach var="list" items="${geReqFileDtoList}" varStatus="status">
<tr>
<td style="width: 40%">${list.fileName}
</td>
<td style="width: 30%">
<c:if test="${list.fileFolderName!=reqId and list.fileFolderName!='請選擇'}">${list.fileFolderName}</c:if>
</td>
<td style="width: 30%">
<a height="650" width="850" class="button mr5" href="<%=appRoots%>/require/getFilePath.do?filePath=${list.filePath}" [minable=true,maxable=true] rel="downLoadFile" title="下載" >
<span>下載</span>
</a>
<a class="button mr5" href ="<%=appRoots%>/require/deleteFile.do?filePath=${list.filePath}&reqId=${reqId}&reqName=${reqName}" target="ajaxTodo" rel="delete" title="確認要刪除嗎">
<span>刪除</span>
</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
</div>
後臺代碼:
@RequestMapping("/downLoadFile")
public void downLoadFile(HttpServletRequest request,HttpServletResponse response,@Param("FileName") String FileName,@Param("reqId") String reqId) throws Exception {
//獲取服務器項目路徑
String oraclePath =System.getProperty("user.dir");
String path = oraclePath+"/productTool/File/"+reqId; // 路徑
File f = new File(path);
File fa[] = f.listFiles();
for (int i = 0; i < fa.length; i++) {
File fs = fa[i];
if(fs.getName().contains(FileName)){
dFile(fs,request,response);
}
}
}
public static void dFile(File file,HttpServletRequest request,HttpServletResponse response) throws Exception{
InputStream ins = new FileInputStream(file);
/* 設置文件ContentType類型,這樣設置,會自動判斷下載文件類型 */
response.setContentType("multipart/form-data");
/* 設置文件頭:最後一個參數是設置下載文件名 */
String formFileName = new String(file.getName().getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;filename="+formFileName);
try{
OutputStream os = response.getOutputStream();
byte[] b = new byte[1024];
int len;
while((len = ins.read(b)) > 0){
os.write(b,0,len);
}
os.flush();
os.close();
ins.close();
}catch (Exception e){
e.printStackTrace();
}
}
3.文件刪除
文件刪除就很簡單了,這裏用了FileUtils工具類,這個類裏有很多方法,比起傳統的字符流,字節流,要來的方便的多,絕大部分時候都可以替代,不過有一個功能我沒有用這個工具類實現成功,就是向同一文件裏循環寫入數據而不覆蓋,我至今還是用FileWriter的newLine()方法實現的。
@RequestMapping("/deleteFile")
@ResponseBody
public AjaxResult deleteFile(ModelAndView mav,@Param("filePath")String filePath,@Param("reqId")String reqId,@Param("reqName")String reqName){
boolean result=true;
AjaxResult ar=new AjaxResult();
FileUtils.deleteFile(new File(filePath));
try {
if(result){
ar= new AjaxResult("200", "文件刪除成功");
ar.setCallbackType("forward");
JSONObject json=new JSONObject();
json.put("reqId", reqId);
json.put("reqName", reqName);
// ar.setForwardUrl("/require/GeReqMainQuery.do?json="+json.toString());
}
} catch (Exception e) {
result=false;
ar=new AjaxResult("300", "文件刪除失敗");
}
return ar;
}
最後這裏提供一個查出路徑下所有文件的方法。
這個方法可以遍歷當前目錄下所有文件及其文件夾的名稱和絕對路徑,有幾個涉及到根據文件路徑取某些特定值的方法:這裏的file即下面循環中的file2,文件數組中的某一個文件對象
//文件名全稱
String fullName=file.getOriginalFilename();
//文件名前綴
String fileName=fullName.substring(0, fullName.indexOf("."));
//文件名後綴/文件類型
String fileType=fullName.substring(fullName.indexOf(".")+1, fullName.length());
//文件名:file2.getName()
//文件的絕對路徑:file2.getAbsolutePath()
//file2.getParent() 指定路徑的上一層路徑,例如E:/zzz.txt,這個方法取到的值就是E盤目錄下
public void traverseFolder1(String path) {
int fileNum = 0, folderNum = 0;
File file = new File(path);
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夾:" + file2.getAbsolutePath());
list.add(file2);
foldeNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
fileNum++;
}
}
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
System.out.println("文件夾:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
System.out.println("文件:" + file2.getAbsolutePath());
fileNum++;
}
}
}
} else {
System.out.println("文件不存在!");
}
System.out.println("文件夾共有:" + folderNum + ",文件共有:" + fileNum);
}