java上傳資料夾檔案
javaweb上傳檔案
上傳檔案的jsp中的部分
上傳檔案同樣可以使用form表單向後端發請求,也可以使用 ajax向後端發請求
1.通過form表單向後端傳送請求
<form id="postForm" action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">
<div class="bbxx wrap">
<inputtype="text" id="side-profile-name" name="username" class="form-control">
<inputtype="file" id="example-file-input" name="avatar">
<button type="submit" class="btn btn-effect-ripple btn-primary">Save</button>
</div>
</form>
改進後的程式碼不需要form標籤,直接由控制元件來實現。開發人員只需要關注業務邏輯即可。JS中已經幫我們封閉好了
this.post_file =function()
{
$.each(this.ui.btn,function(i, n) { n.hide();});
this.ui.btn.stop.show();
this.State =this.Config.state.Posting;//
this.app.postFile({ id:this.fileSvr.id, pathLoc:this.fileSvr.pathLoc, pathSvr:this.fileSvr.pathSvr,lenSvr:this.fileSvr.lenSvr, fields:this.fields });
};
通過監控工具可以看到控制元件提交的資料,非常的清晰,除錯也非常的簡單。
2.通過ajax向後端傳送請求
$.ajax({
url : "${pageContext.request.contextPath}/UploadServlet",
type : "POST",
data : $( '#postForm').serialize(),
success : function(data) {
$( '#serverResponse').html(data);
},
error : function(data) {
$( '#serverResponse').html(data.status + " : " + data.statusText + " : " + data.responseText);
}
});
ajax分為兩部分,一部分是初始化,檔案在上傳前通過AJAX請求通知服務端進行初始化操作
this.md5_complete =function(json)
{
this.fileSvr.md5 = json.md5;
this.ui.msg.text("MD5計算完畢,開始連線伺服器...");
this.event.md5Complete(this, json.md5);//biz event
varloc_path = encodeURIComponent(this.fileSvr.pathLoc);
varloc_len =this.fileSvr.lenLoc;
varloc_size =this.fileSvr.sizeLoc;
varparam = jQuery.extend({},this.fields,this.Config.bizData, { md5: json.md5, id:this.fileSvr.id, lenLoc: loc_len, sizeLoc: loc_size, pathLoc: loc_path, time:newDate().getTime() });
$.ajax({
type:"GET"
, dataType:'jsonp'
, jsonp:"callback"//自定義的jsonp回撥函式名稱,預設為jQuery自動生成的隨機函式名
, url:this.Config["UrlCreate"]
, data: param
, success:function(sv)
{
_this.svr_create(sv);
}
, error:function(req, txt, err)
{
_this.Manager.RemoveQueuePost(_this.fileSvr.id);
alert("向伺服器傳送MD5資訊錯誤!"+ req.responseText);
_this.ui.msg.text("向伺服器傳送MD5資訊錯誤");
_this.ui.btn.cancel.show();
_this.ui.btn.stop.hide();
}
, complete:function(req, sta) { req =null; }
});
};
在檔案上傳完後向伺服器傳送通知
this.post_complete =function(json)
{
this.fileSvr.perSvr ="100%";
this.fileSvr.complete =true;
$.each(this.ui.btn,function(i, n)
{
n.hide();
});
this.ui.process.css("width","100%");
this.ui.percent.text("(100%)");
this.ui.msg.text("上傳完成");
this.Manager.arrFilesComplete.push(this);
this.State =this.Config.state.Complete;
//從上傳列表中刪除
this.Manager.RemoveQueuePost(this.fileSvr.id);
//從未上傳列表中刪除
this.Manager.RemoveQueueWait(this.fileSvr.id);
varparam = { md5:this.fileSvr.md5, uid:this.uid, id:this.fileSvr.id, time:newDate().getTime() };
$.ajax({
type:"GET"
, dataType:'jsonp'
, jsonp:"callback"//自定義的jsonp回撥函式名稱,預設為jQuery自動生成的隨機函式名
, url: _this.Config["UrlComplete"]
, data: param
, success:function(msg)
{
_this.event.fileComplete(_this);//觸發事件
_this.post_next();
}
, error:function(req, txt, err) { alert("檔案-向伺服器傳送Complete資訊錯誤!"+ req.responseText); }
, complete:function(req, sta) { req =null; }
});
};
這裡需要處理一個MD5秒傳的邏輯,當伺服器存在相同檔案時,不需要使用者再上傳,而是直接通知使用者秒傳
this.post_complete_quick =function()
{
this.fileSvr.perSvr ="100%";
this.fileSvr.complete =true;
this.ui.btn.stop.hide();
this.ui.process.css("width","100%");
this.ui.percent.text("(100%)");
this.ui.msg.text("伺服器存在相同檔案,快速上傳成功。");
this.Manager.arrFilesComplete.push(this);
this.State =this.Config.state.Complete;
//從上傳列表中刪除
this.Manager.RemoveQueuePost(this.fileSvr.id);
//從未上傳列表中刪除
this.Manager.RemoveQueueWait(this.fileSvr.id);
//新增到檔案列表
this.post_next();
this.event.fileComplete(this);//觸發事件
};
這裡可以看到秒傳的邏輯是非常 簡單的,並不是特別的複雜。
var form = new FormData();
form.append("username","zxj");
form.append("avatar",file);
//var form = new FormData($("#postForm")[0]);
$.ajax({
url:"${pageContext.request.contextPath}/UploadServlet",
type:"post",
data:form,
processData:false,
contentType:false,
success:function(data){
console.log(data);
}
});
java部分
檔案初始化的邏輯,主要程式碼如下
FileInf fileSvr=newFileInf();
fileSvr.id = id;
fileSvr.fdChild =false;
fileSvr.uid = Integer.parseInt(uid);
fileSvr.nameLoc = PathTool.getName(pathLoc);
fileSvr.pathLoc = pathLoc;
fileSvr.lenLoc = Long.parseLong(lenLoc);
fileSvr.sizeLoc = sizeLoc;
fileSvr.deleted =false;
fileSvr.md5 = md5;
fileSvr.nameSvr = fileSvr.nameLoc;
//所有單個檔案均以uuid/file方式儲存
PathBuilderUuid pb =newPathBuilderUuid();
fileSvr.pathSvr = pb.genFile(fileSvr.uid,fileSvr);
fileSvr.pathSvr = fileSvr.pathSvr.replace("\\","/");
DBConfig cfg =newDBConfig();
DBFile db = cfg.db();
FileInf fileExist =newFileInf();
booleanexist = db.exist_file(md5,fileExist);
//資料庫已存在相同檔案,且有上傳進度,則直接使用此資訊
if(exist && fileExist.lenSvr > 1)
{
fileSvr.nameSvr= fileExist.nameSvr;
fileSvr.pathSvr= fileExist.pathSvr;
fileSvr.perSvr= fileExist.perSvr;
fileSvr.lenSvr= fileExist.lenSvr;
fileSvr.complete= fileExist.complete;
db.Add(fileSvr);
//觸發事件
up6_biz_event.file_create_same(fileSvr);
}//此檔案不存在
else
{
db.Add(fileSvr);
//觸發事件
up6_biz_event.file_create(fileSvr);
FileBlockWriter fr =newFileBlockWriter();
fr.CreateFile(fileSvr.pathSvr,fileSvr.lenLoc);
}
接收檔案塊資料,在這個邏輯中我們接收檔案塊資料。控制元件對資料進行了優化,可以方便除錯。如果用監控工具可以看到控制元件提交的資料。
booleanisMultipart = ServletFileUpload.isMultipartContent(request);
FileItemFactory factory =newDiskFileItemFactory();
ServletFileUpload upload =newServletFileUpload(factory);
List files =null;
try
{
files = upload.parseRequest(request);
}
catch(FileUploadException e)
{//解析檔案資料錯誤
out.println("read file data error:"+ e.toString());
return;
}
FileItem rangeFile =null;
//得到所有上傳的檔案
Iterator fileItr = files.iterator();
//迴圈處理所有檔案
while(fileItr.hasNext())
{
//得到當前檔案
rangeFile = (FileItem) fileItr.next();
if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))
{
pathSvr = rangeFile.getString();
pathSvr = PathTool.url_decode(pathSvr);
}
}
booleanverify =false;
String msg ="";
String md5Svr ="";
longblockSizeSvr = rangeFile.getSize();
if(!StringUtils.isBlank(blockMd5))
{
md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());
}
verify = Integer.parseInt(blockSize) == blockSizeSvr;
if(!verify)
{
msg ="block size error sizeSvr:"+ blockSizeSvr +"sizeLoc:"+ blockSize;
}
if(verify && !StringUtils.isBlank(blockMd5))
{
verify = md5Svr.equals(blockMd5);
if(!verify) msg ="block md5 error";
}
if(verify)
{
//儲存檔案塊資料
FileBlockWriter res =newFileBlockWriter();
//僅第一塊建立
if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));
res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);
up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));
JSONObject o =newJSONObject();
o.put("msg","ok");
o.put("md5", md5Svr);
o.put("offset", blockOffset);//基於檔案的塊偏移位置
msg = o.toString();
}
rangeFile.delete();
out.write(msg);
注:
1.上面的java部分的程式碼可以直接使用,只需要將上傳的圖片路徑及收集資料並將資料寫入到資料庫即可
2.上面上傳檔案使用到了位元組流,其實還可以使用別的流,這個需要讀者自己在下面完善測試
3. BeanUtils是一個工具 便於將實體對應的屬性賦給實體
4.上傳檔案不能使用 request.getParameter("")獲取引數了,而是直接將request解析,通過判斷每一項是檔案還是非檔案,然後進行相應的操作(檔案的話就是用流來讀取,非檔案的話,暫時儲存到一個map中。)
後端程式碼邏輯大部分是相同的,目前能夠支援MySQL,Oracle,SQL。在使用前需要配置一下資料庫,可以參考我寫的這篇文章: