1. 程式人生 > >Java+JavaScript完成上傳下載,不需要流處理(不看保證你後悔)

Java+JavaScript完成上傳下載,不需要流處理(不看保證你後悔)

今天教大家一個不用IO,不用外掛,就可以進行檔案上傳與下載的功能。

前端使用bootstrap+JSP+JS,後端是java,資料庫暫選mysql(因為關係資料庫就那幾個,哪個簡單用哪個)。

看下資料庫:




file_data欄位是用來儲存解析後的資料的,由於解析後,十分龐大,不得不用LongBlob(不知道的請自行腦補),Java裡我用String對應。

另外要說下,mysql資料庫有大小限制,請找到mysql的my.ini檔案,找到'max_allowed_packet=1M'這個欄位,如果沒有,請自行新增。意思就是,最大存1M的內容,不妨將它設為100M或者更高。

下面我們看看JSP:

<div>
<form id="form" enctype="multipart/form-data">
	<div class="form-group">
			<div class="col-sm-2" >
				<label for="fileUpload" class="btn btn-success"><i class="glyphicon glyphicon-plus">上傳</i></label>
				<input id="fileUpload" name="fileUpload" type="file" style="display:none">
			</div>
			<div style="border:1px dashed #000; height:76px;width:86px;margin-left: 100px;"> 
				<label class ="col-sm-2control-label">
				<img id="image" src =" " alt="" style="height:76px;width:86px;margin-top: -33px;">
				
				</label>
			</div>
			<br>
			<!--儲存檔案的解析資料 -->
			<input id="file_data" name="file_data" type="text" style="display: none;">
			<div class="col-sm-2" >
				<label for="submit" class="btn btn-success"><i class="glyphicon glyphicon-ok">提交</i></label>
				<input id="submit" name="submit" type="button" onclick="submitFile();" style="display:none">
				</div>
				<div class="col-sm-2" style="margin-left: -87px;">
					<label for="reset" class="btn btn-danger"><i class="glyphicon glyphicon-remove">取消</i></label>
						<input class="btn btn-danger" id="reset" name="reset" onclick="resetUpload();" type="reset" style="display:none">
				</div>
			</div>
	</form>
</div>
以上一大堆,唯一關鍵的就是
<input id="fileUpload" name="fileUpload" type="file" style="display:none">
<input id="file_data" name="file_data" type="text" style="display: none;">
一個是檔案上傳的,一個是上傳後解析內容,將內容儲存的。細心的朋友看到上面用到lable標籤,請不要自行刪除,這是我用來做樣式的,因為以往input會產生框,現在就不會了,你看:

更細心的朋友會看到有form表單,而且格式為enctype="multipart/form-data"。不錯,我要用到spring的MultipartFile介面,但我必須宣告下,我絕不會用它來進行資料轉換與上傳,僅僅是用來接收資料,用這個必須進行XML配置,請自行百度。簡單的說,我完全用form表單也是可以的,這是我原來想做視訊解析時搞的,也就沒改。為什麼說僅僅form就可以呢?請往下看。

這是我的JS,

$(function(){
    var path,clip = $("#image"),FileReader = window.FileReader;  
    $("#fileUpload").change(function() {  
        if (FileReader) {//chrome瀏覽器處理  
            var reader = new FileReader(),  
                file = this.files[0];  
            	reader.onload = function(e) {  
                    clip.attr("src", e.target.result);//這裡是把檔案轉成64位資料存入<img>中的src裡  
                };  
                reader.readAsDataURL(file);   
            setTimeout("showchange()",1000);  
        }else{//其他瀏覽器處理,火狐在這裡就不寫出來了,網上資料很多  
            path = $(this).val();
        	alert(path)
            if (/"\w\W"/.test(path)) {  
                path = path.slice(1,-1);  
            }  
            clip.attr("src",path);  
        }  
    });  
})
//存入資料  
function showchange(){
        var s1 = $("#image").attr("src");
//這是JSP裡面的隱藏輸入框,用來儲存解析後的資料的
        $("#file_data").val(s1);
}

上段程式碼是網上看到某人寫的解析檔案方法,我拷貝過來。

大家都知道form提交時會重新整理頁面,效果不是很樂觀,所以這裡我選擇ajax提交form表單就不會重新整理了:

//檔案上傳
function submitFile(){
	$.ajax({  
	    url: getProjectRootUrl() + "/file/uploadFile.do",
	    type: 'POST',
	    cache: false,
	    data: new FormData($("#form")[0]),  
	    processData: false,  
	    contentType: false,
	    success: function (result) {
	    	alert(result);
	    },  
	    error: function (err) {  
	    }  
	}); 
}

上圖中getProjectRootUrl()方法是獲取專案的路徑,目的是讓它跳轉到我的Controller裡面,不管你用啥,只要能進Controller就行。下面看下後臺:
@RequestMapping("/uploadFile")
	@ResponseBody
	public String testUploadFile(String file_data,HttpServletRequest request,@RequestParam("fileUpload") MultipartFile file) {
		FileUpload fileUpload = new FileUpload();
		if (file.isEmpty()) {
			return "檔案為空";
		}
		// 獲取檔名
		String fileName = file.getOriginalFilename();
		// 獲取檔案的字尾名
		String suffixName = fileName.substring(fileName.lastIndexOf("."));
		// 檔案上傳後的路徑
		String filePath = "D://file//";

		String fileUUIDName = UUID.randomUUID().toString().replaceAll("-", "")
				+ suffixName;
		File dest = new File(filePath + fileUUIDName);
		// 檢測是否存在目錄
		if (!dest.getParentFile().exists()) {
			dest.getParentFile().mkdirs();
		}
		try {
			file.transferTo(dest);
			//設定檔案相關屬性
			fileUpload.setFile_name(fileName);
			fileUpload.setFile_path(dest.getPath());
			fileUpload.setFile_data(file_data);
			fileUpload.setFile_create_by(String.valueOf(request.getSession().getAttribute("username")));
			fileUpload.setFile_create_time(BaseUtil.getDateTime("yyyy-MM-dd HH:mm:ss",new Date()));
			insertFile(fileUpload);
			
			return "上傳成功!";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "上傳失敗!";
	}

以上一堆都沒啥大用,唯一的用處是insertFile(fileUpload)方法,向資料庫新增資料,至關重要的欄位還記得嗎?file_data欄位,他是長Blob型別,而我是怎麼接收的?看方法的引數,是不是僅僅用String來收的,通過前臺解析後,存入一個隱藏的input裡,然後提交表單時,帶過來。

下面讓大家看看,我一直提到的解析的資料是個什麼鬼:




控制檯從data開始都是解析後的資料,看到了吧,是不是十分龐大!如果超過1M的檔案,就會解析十分慢,甚至被拖垮!所以只能進行1M內的檔案處理,畢竟咱這不是什麼高大上的技術。給大家演示下,將這些解析的東西直接拷貝,貼上到瀏覽器位址列,如果是圖片就會立刻顯示,如果是檔案,就會立刻呼叫瀏覽器的下載功能!

總結一下,至關重要的就是在於JS解析,也就是上面的一大串東西。思路就是,將解析好的東西存入庫中,然後呼叫時用JS,舉例子:

//檔案下載
function upload(file_id){
	alert(file_id);
	$.ajax({
		type:'post',
		url:getProjectRootUrl()+'/file/getFileByFileId.do',
		contentType:"application/json",
		dataType:'json',
		data:JSON.stringify({"file_id":file_id}),
		success: function(data){
			window.location.href=data.file_data;
		}
	});
}

看到了吧,是不是超級簡單,至於你怎麼將解析後的資料存庫,我不管, 只要能存進去就好。感謝觀看。