java web應用上傳圖片詳解
阿新 • • 發佈:2019-01-22
本文涉及如下技術:
- 前端:extJS
- 後端:struts2, tomcat等
前端實現
前端用的是ExtJS框架,實現了一個簡單的圖片上傳功能。由於我本身對前端技術也不是很熟悉,這部分只是班門弄斧隨便講下。
基本思路是這樣的:
點選 “上傳” 按鈕時,呼叫一個js的函式,這個函式通過呼叫後端action來完成檔案上傳的操作。
js函式實現如下:
function uploadImg(){
var filePath=uploadVar.getValue();
if(filePath==''){
Ext.MessageBox.alert("提示" ,"請選擇圖片!");
return;
}
imageForm.getForm().getEl().dom.enctype="multipart/form-data";
imageForm.getForm().submit({
waitMsg : "圖片上傳中...",
waitTitle: '提示',
method: 'POST',
url:'uploadImage.action?flag=aa&id='+curSelNode.id,
success : function (form, action){
var image = Ext.get('picpath').dom;
var fileUrl=action.result.fileUrl;
if(fileUrl==null || fileUrl==''){
image.src = Ext.NOPIC_IMAGE_URL;
}else{
image.src=fileUrl;
}
var form = addOrUpdateAdvertPanelForm.getForm();
form.findField('advertisement.picpath').setValue(fileUrl);
Ext.MessageBox.alert("提示","上傳成功!");
},
failure : function(){
Ext.MessageBox.alert("提示","上傳失敗!");
}
});
}
url欄位指向了請求的action地址(uploadImage.action)。下面就是伺服器端的事了。
伺服器端實現
我首先在struts.xml裡配置action,
<!-- 上傳圖片Action配置 -->
<action name="uploadImage" class="imageUploadAction" method="uploadImageExt">
<result >pages/uploadSuccess.jsp</result>
</action>
這裡告訴伺服器actio對應的類和方法,接下來是具體實現:
@Controller("imageUploadAction")
public class ImageUploadAction {
private static final long serialVersionUID = -7914395488136167452L;
private File file;
private File imgFile; //確保和前端控制元件名一致
private String flag;
private String fileUrl;
private boolean success = false; // 成功標識
/**
* 上傳圖片-EXT
*/
public String uploadImageExt() {
try {
if (null == this.flag || "".equals(this.flag)) {
this.success = false;
return SUCCESS;
}
String path = null; // 圖片物理根路徑
String outPath = null; // 圖片伺服器URL
//從配置檔案讀取物理路徑和訪問路徑
String path = Config.getProperty("UPLOAD_PATH");
String outPath = Config.getProperty("UPLOAD_URL");
// 上傳檔案方法
this.fileUrl = this.uploadCommon(path, outPath, this.imgFile,
this.imgFile.getAbsolutePath(), this.getCurrentUser()
.getUserid().toString());
this.success = true;
} catch (Exception e) {
this.success = false;
} finally {
return SUCCESS;
}
}
public String uploadCommon(String path, String outPath, File file,
String fileName, String userid) {
String r = "";
try {
// 獲取副檔名
String extName = "";
if (fileName.lastIndexOf(".") >= 0) {
extName = fileName.substring(fileName.lastIndexOf("."));
}
if (".tmp".equals(extName)) {
extName = ".jpg";
}
// 生成資料夾:編號+時間(相對路徑)
String midPath = (null != id && !"".equals(id)
&& !"null".equals(id) ? id + "/" : "")
+ DateUtil.date2String(new Date(), "yyyyMMdd") + "/";
// 生成檔名稱,具體的秒的時間
String imgName = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date()) + new Random().nextInt(100) + extName;
// 圖片物理路徑=WEB物理路徑+相對路徑+檔名
String filePath = path + midPath + imgName;
// 完整的圖片訪問URL
String imgUrl = outPath + midPath + imgName;
// 取HTTP請求流,將其寫成圖片檔案
FileInputStream inFile = new FileInputStream(file);
double fileSize = inFile.available() / 1024; // 單位KB
File f_img = new File(path + midPath);
if (!f_img.exists()) {
f_img.mkdirs();
}
FileOutputStream outFile = new FileOutputStream(filePath);
byte[] buffer = new byte[1024];
int i = 0;
while ((i = inFile.read(buffer)) != -1) {
outFile.write(buffer, 0, i);
}
outFile.flush();
outFile.close();
inFile.close();
r = imgUrl;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return r;
}
這樣我就把圖片儲存到了本地電腦的一個物理路徑,比如說這個路徑是類似這樣:
C:\img\upload\aa\1\20170629\20170629_09221534.jpg
訪問路徑我在配置檔案裡是這樣寫的:
http://localhost:8080/upload/img/aa/
配置虛擬路徑
圖片上傳成功後,我們還需要通過http訪問這個圖片。但是前面上傳的圖片並不在tomcat目錄下,該如何訪問呢?
有人可能要說,那你在配置檔案裡把物理路徑寫成tomcat專案下的不就可以了嗎?
確實是可以,但是為了以後軟體升級的方便,我會選擇某些上傳的靜態資源,如圖片、視訊等放置在伺服器tomcat目錄外,網站下次升級,只更新網站的war包,原靜態資源可以不用動。
這就需要配置下tomcat,告訴它我們的靜態資源在外部的一個地址。
拿我上面配置的地址為例,編輯Tomcat下的server.xml檔案,在host節點中增加如下的配置:
<Context path="/upload/img/aa/" docBase="C:\img\upload\aa\" reloadable="false" ></Context>