在web項目中文件上傳是十分平常的,對於文件上傳之前用過幾種方法都比較實用。
一、基於Apache common fileupload
二、基於servlet和JavaScript FileReader
三、框架裏自帶的文件上傳
他們各自適用於不同的場合個人認爲:第一種適合較大的文件上傳,第二種適合圖片上傳並且可以上傳預覽但不兼容所有瀏覽器,第三種就是你用到ssm、ssh、springboot框架時適用
今天我們先講第二、基於servlet和JavaScript FileReader
1、首先我們先了解下FileReader
FileReader接口提供了一個異步API,使用該API可以在瀏覽器主線程中異步訪問文件系統,讀取文件中的數據。到目前爲止,只有FF3.6+和Chrome6.0+實現了FileReader接口。
FileReader接口的方法
FileReader接口有4個方法,其中3個用來讀取文件,另一個用來中斷讀取。無論讀取成功或失敗,方法並不會返回讀取結果,這一結果存儲在result屬性中。
方法名 | 參數 | 描述 |
---|---|---|
readAsBinaryString | file | 將文件讀取爲二進制編碼 |
readAsText | file,[encoding] | 將文件讀取爲文本 |
readAsDataURL | file | 將文件讀取爲DataURL |
abort | (none) | 終端讀取操作 |
FileReader接口事件
FileReader接口包含了一套完整的事件模型,用於捕獲讀取文件時的狀態。
事件 | 描述 |
onabort | 中斷 |
onerror | 出錯 |
onloadstart | 開始 |
onprogress | 正在讀取 |
onload | 成功讀取 |
onloadend | 讀取完成,無論成功失敗 |
2、實際演示通過FileReader接口的方法我們怎麼獲取圖片文件
<!--添加一個文件輸入框並賦予一個事件我這裏採用onchange你也可以用別的-->
<input type="file" id="inputBox" οnchange="selectFile('inputBox','15574478888','1','xx')">
<script>
<!--函數本身你可以多傳入幾個信息用於不同的操作或判斷這個人是否可以上傳
yourinputID:上面那個文件輸入框,即他的id值;
account:上傳人的賬號;
operation:操作數我是將1設爲添加,2設爲刪除
name:只用刪除時用到,它爲刪除的文件名
-->
function selectFile(yourinputID,account,operation,name) {
var type = null;
var data = null;
var inputBox = document.getElementById(yourinputID);
var reader = new FileReader();
<!--如果輸入框的文件不爲空,則讀取文件-->
if (inputBox.files[0] != null) {
reader.readAsDataURL(inputBox.files[0]);//發起異步請求
reader.onload = function () {
<!--獲取文件的類型和數據-->
var type = this.result.substring(0, this.result.indexOf("base64") - 1).split("/")[1];
var data = this.result.substring(this.result.indexOf("base64") + 7, this.result.length);
console.info(this.result);
console.info(type);
console.info(data);
<!--類型和數據不爲空時則發送給後臺-->
if(type!=null&&data!=null){
$.ajax({
//servlet url
url : "請求的servlet",
//請求方式get、post
type : 'post',
//向後臺傳送的數據
data: {'type': type,'data':data,'account':account,'operation':operation,"name":name},
//傳送的數據格式
dataType : 'json',
success : function(result) {
console.info(result);
}
});
}
}
}
}
</script>
var type = this.result.substring(0, this.result.indexOf("base64") - 1).split("/")[1];
var data = this.result.substring(this.result.indexOf("base64") + 7, this.result.length);
對於前端js代碼大家可能或不清楚爲什麼要進行字符串的截取。這是因爲FileReader是將文件讀取成base64格式。
base64(百度百科)
Base64是網絡上最常見的用於傳輸8Bit字節碼的編碼方式之一,Base64就是一種基於64個可打印字符來表示二進制數據的方法。可查看RFC2045~RFC2049,上面有MIME的詳細規範。
Base64編碼是從二進制到字符的過程,可用於在HTTP環境下傳遞較長的標識信息。例如,在Java Persistence系統Hibernate中,就採用了Base64來將一個較長的唯一標識符(一般爲128-bit的UUID)編碼爲一個字符串,用作HTTP表單和HTTP GET URL中的參數。在其他應用程序中,也常常需要把二進制數據編碼爲適合放在URL(包括隱藏表單域)中的形式。此時,採用Base64編碼具有不可讀性,需要解碼後才能閱讀。
簡單來說他就是一種文件的表示形勢和二進制類似
我先運行下完整的項目觀察一下:
第一段輸出爲:console.info(this.result);
第二段輸出爲:console.info(type);
第三段輸出爲:console.info(data);
上述輸出即爲處理好後的數據。
那沒截取之前他表示的形式是這樣的:
data:image/png;base64,iVBORAAAANSUhEUg.....
data:image/png;base64,iVBORw0KGgoAAACA.....
data:image/png;聲明類型
base64:聲明格式
所以我們會有字符的截取
var type = this.result.substring(0, this.result.indexOf("base64") - 1).split("/")[1];(獲取圖片是什麼格式的例如:png、jpg、jpeg。。。)
var data = this.result.substring(this.result.indexOf("base64") + 7, this.result.length);(獲取圖片具體內容)
明白這裏那就簡單了,我們只需要將這些數據發送給後臺就可以了。
3.編輯後臺servlet
後臺沒什麼好說的就是獲取參數;base64解碼;創建對應的文件;添加成功後將圖片url返回;
package com.lb.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Calendar;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/Allimg")
public class Allimg extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("111");
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8;");
PrintWriter outInfo = response.getWriter();
String account = request.getParameter("account").trim();
String operation = request.getParameter("operation").trim();
String name = request.getParameter("name").trim();
String type = request.getParameter("type").trim();
String data = request.getParameter("data").trim();
sun.misc.BASE64Decoder base64Decoder = new sun.misc.BASE64Decoder();
System.out.println(request.getServletContext().getRealPath(""));
String path = "/usr/local/nginx/html/FruitImg/";
Calendar calendar = Calendar.getInstance();
if("1".equals(operation)) {
File f = new File(path+account+calendar.get(Calendar.MINUTE)+calendar.get(calendar.SECOND)+calendar.get(calendar.MILLISECOND)+"."+type);
f.createNewFile();
OutputStream out = new FileOutputStream(f);
out.write(base64Decoder.decodeBuffer(data));
out.close();
outInfo.println("{\"url\":"+"\""+account+calendar.get(Calendar.MINUTE)+calendar.get(calendar.SECOND)+calendar.get(calendar.MILLISECOND)+"."+type+"\"}");
}else if("2".equals(operation)) {
File file=new File(name);
if(file.exists()&&file.isFile()) {
file.delete();
outInfo.println("2");
}
}
}
}