功能需求描述
- 需要一個能夠顯示員工頭像的區域,點擊區域可更新圖片。
- 圖片爲服務器文件存儲(之所以不放到數據庫中,爲了防止數據庫過大導致備份和遷移時效率降低)
思路描述
上傳員工頭像功能開發流程:
-
頭像上傳區域:
1.1 設置頭像點擊事件
1.2 設置默認頭像
1.3 在點擊事件中,增加圖片上傳預覽的彈出框
1.4 圖片上傳後預覽
1.5 增加返回參數,能夠返回保存到服務器上的圖片路徑給父頁面 -
圖片保存顯示
2.1 根據圖片路徑,刷新當前圖片顯示
2.2 點擊保存後,將最新的圖片路徑保存到實體內
2.3 編輯後能正常顯示頭像圖片信息
用到的主要技術
- 圖片預覽用到了
var reader = new FileReader();
渲染方法,讀取本地上傳的緩存圖片。 - 圖片上傳需要用到文件流以及File對象持久化的一些方法
處理流程
核心代碼
1. 設置圖片顯示區域,綁定點擊事件uploadImage。同時,增加一個記錄圖片上傳後返回路徑的隱藏input,實現圖片文件路徑的保存
<div class="col-xs-2" align="right">
<img src="${pageContext.request.contextPath}/image/login/userDefault.jpg" id="img"
name="img" οnclick="javascript:uploadImage(this.id);"
style="cursor:pointer;width:147px;height:206px;">
<input type="hidden" id="photoPath" name="photoPath" value="${entity.photoPath}">
</div>
2. 點擊事件函數(此處方法給封裝過的方法,用的是layui的組件,後臺用的springmvc,其他框架可根據自己框架進行調整。無非就是給後臺傳遞一個參數,然後跳轉到另外一個頁面)
//頭像圖片點擊函數
function uploadImage() {
//彈出圖片上傳
var url = "${pageContext.request.contextPath}/administration/hrManage/personInfo/toImageUploadJsp.do";
var obj = {
area: ['40%', '70%'],
url: url,
title: '上傳圖片',
id: 'personInfoAdd'
};
getDialogPage(obj);
}
3. 後臺處理點擊後,跳轉到圖片上傳頁面的方法
@RequestMapping("/toImageUploadJsp")
public ModelAndView toImageUploadJsp(){
ModelAndView modelAndView = new ModelAndView();
try {
modelAndView.addObject("formBtn", getFormBut(EditStatus.valueOf(1), false, false));//表單按鈕
modelAndView.setViewName("/web/administration/hrManage/imageUpload");
} catch (Exception e) {
log.error("跳轉到跳轉到圖片上傳頁面失敗",e);
modelAndView.setViewName("error/500");
}
return modelAndView;
}
4. 上傳頁面代碼
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE>
<html>
<head>
<title>用戶簽名</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<jsp:include page="/initlib/initCommon.jsp"></jsp:include>
<jsp:include page="/initlib/initEditCss.jsp"></jsp:include>
<style type="text/css">
</style>
</head>
<body>
<div style="width: 96%; height: 90%;">
<legend>基本信息</legend>
<hr style="margin-top:-20px;margin-left: 4%">
<form id="dataForm" class="form-horizontal" role="form" method="post">
<div class="form-group form-group-xs">
<label for="uploadFile" class="col-xs-2 control-label"><a class="require"><i
class="icon-Asterisk"></i></a>上傳文件</label>
<div class="col-xs-2">
<input type="file" name="uploadFile" id="uploadFile" style="font-size:
10px;font-family: Microsoft YaHei;border-style: inset;border-width: 2px;padding: 1px;" οnchange="preview(this)">
</div>
</div>
<div class="form-group form-group-xs">
<label for="previewImg" class="col-xs-2 control-label"><a class="require"><i
class="icon-Asterisk"></i></a>預覽圖片</label>
<div class="col-xs-6">
<img id="previewImg" style="width:147px;height:206px;"/>
</div>
</div>
</form>
<div id="footer">${formBtn}</div>
</div>
</body>
</html>
<script>
$(document).ready(function () {
});
function saveClick() {
if ($("#uploadFile").val() == "") {
layer.msg('請選擇要上傳的文件', {icon: 0});
return;
}
layer.confirm('上傳將會清空原有頭像,是否繼續操作?', {
btn: ['確認', '取消'] //按鈕
}, function () {
var index = layer.load();
$.ajaxFileUpload({
url: "${pageContext.request.contextPath}/administration/hrManage/personInfo/imageUpload.do",
secureuri: false,
fileElementId: "uploadFile",
dataType: 'text',
type: "POST",
success: function (data, status) {
layer.close(index);
var res = data.substring((data.indexOf('>') + 1), (data.indexOf('}') + 1));
var json = $.parseJSON(res);
if (json.success) {
//todo 處理返回的圖片路徑
//parent.$("#photoPath").attr("src",json.obj);
parent.initImage(json.obj);
layer.msg(json.msg, {icon: 6, time: 1000}, function () {
closeClick();
});
} else {
layer.msg(json.msg, {icon: 5});
}
},
error: function (data, status, e) {
}
});
}, function () {
}
);
}
//預覽圖片
function preview(obj) {
var file = obj.files[0];
//file.size 單位爲byte 可以做上傳大小控制
console.log("file.size = " + file.size);
var reader = new FileReader();
//讀取文件過程方法
reader.onabort = function (e) {
console.log("中斷讀取....");
}
reader.onerror = function (e) {
console.log("讀取異常....");
}
reader.onload = function (e) {
var img = document.getElementById("previewImg");
img.src = e.target.result;
}
reader.readAsDataURL(file)
}
</script>
Tips: 頁面中包含三部分內容:
1) 添加一個file類型的輸入框,用於選擇本地可上傳的文件。
2) 增加了一個function preview(obj)
函數,用於處理上傳後的圖片預覽功能
3) 添加一個function saveClick()
函數,用於處理圖片文件校驗、上傳圖片以及圖片回調問題
4)上傳成功後的回調函數parent.initImage(json.obj);
將在後面進行介紹
5.圖片流後臺保存函數
@ResponseBody
@RequestMapping("/imageUpload")
public Json imageUpload(HttpSession session, @RequestParam("uploadFile") CommonsMultipartFile uplodaFile) {
Json json = new Json();
try {
String contentType = uplodaFile.getContentType();
String fileName = DateUtil.getNowDateTime("YYYY-MM-DD")+uplodaFile.getOriginalFilename();
String folderPath = "E:/userImage";
if (uplodaFile.isEmpty()) {
json.setSuccess(false);
json.setMsg("上傳圖片不正確");
return json;
}
try {
File targetFile = new File(folderPath);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
FileOutputStream out = new FileOutputStream(folderPath +"/"+ fileName);
out.write(uplodaFile.getBytes());
out.flush();
out.close();
} catch (Exception e) {
json.setSuccess(false);
json.setMsg("上傳圖片失敗");
return json;
}
json.setSuccess(true);
//返回圖片路徑
json.setObj(folderPath+"/"+fileName);
json.setMsg("上傳圖片成功");
} catch (Exception e) {
log.error(message, e);
json.setSuccess(false);
json.setMsg("上傳圖片失敗"+e.getMessage());
}
return json;
}
- 前臺回調函數功能,1. 保存返回的圖片路徑,2. 動態加載圖片
//初始化員工頭像
function initImage(url) {
if (url != undefined && url != "") {
$("#img").attr("src", "${pageContext.request.contextPath}/administration/hrManage/personInfo/getImage.do?path=" + url);
$("#photoPath").val(url);
} else if ("${entity.photoPath}" != "") {
$("#img").attr("src", "${pageContext.request.contextPath}/administration/hrManage/personInfo/getImage.do?path=" + "${entity.photoPath}");
}
}
- 上文中,調用了一個
getImage
的後臺函數,是因爲我們將圖片保存到服務器上項目外的文件夾內,工程文件無法直接通過路徑對圖片進行讀取。因此需要額外處理。
@ResponseBody
@RequestMapping("/getImage")
public void getImage(String path, HttpServletRequest request, HttpServletResponse response) {
OutputStream os = null;
try {
BufferedImage image = ImageIO.read(new File(path));
response.setContentType("image/png");
os = response.getOutputStream();
ImageIO.write(image, "gif", os);
} catch (IOException e) {
e.printStackTrace();
}
}
總結
- 處理圖片上傳預覽,本次由於時間關係採用自行設計開發的功能頁面,如果此需求其他模塊均需要使用,儘量採用開源的圖片上傳組件,例如Web Uploader一類的。一個是頁面設計更美觀、合理。第二個也是方便集成
- 顯示圖片的方案,本文中採用的方式爲通過文件流的形式,將服務器上存儲的圖片以流的形式讀取到頁面,並返回給前臺。如果你的服務器上已經配置了nginx,建議還是用nginx配置的方式實現圖片等靜態資源的直接讀取功能。(如果有時間,後面可以針對這一細節進行說明)