前端:
直接通過圖片的URL加載圖片
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/afquery.js"></script>
<style>
.main{
}
.main input{
margin: 20px;
}
.main .upload{
background-color: cornflowerblue;
color: #fff;
border: 1px solid #ccc;
border-radius: 1px;
padding: 8px 18px;
}
</style>
</head>
<body>
<div class="main">
<input type="file" class="filebutton" style="display: none" /><br />
<button class="upload" οnclick="selectFile()">選擇文件上傳</button>
<div>
<img class="imagebox" src="" style="width: 300px;" />
</div>
</div>
</body>
<script>
//初始化
var up = new AfUploader();
up.setButton('.filebutton'); // 設置file input控件
up.setUploadUrl('FileUploadService'); // 設置服務URL
up.setLogEnabled( false );
// 事件處理 'start' 'progress' 'complete' 'error' 'abort'
up.processEvent = function(event)
{
if(event == 'progress')
{
Af.log("進度: " + this.progress);
}
else if(event == 'complete')
{
Af.log("完成上傳");
Af.log(this.response);
var jresp = JSON.parse (this.response);
var url = jresp.data.url;
$('.imagebox').attr('src', url);
}
};
//是否允許上傳
up.beforeUpload = function()
{
if(this.file.size > 10*1000000)
{
alert("文件太大!");
return false;
}
return true;
};
function selectFile()
{
up.openFileDialog();
}
</script>
</html>
這裏用到了封裝好的自定義文件上傳工具類(afquery.js):
網址:邵發老師
/*
* 上傳工具類
*/
function AfUploader()
{
this.fileButton = null; // 原生DOM
this.file = null; // 要上傳的文件
this.uploadUrl = null;
this.status = 0; // 0, 1, 100, -1(失敗), -2(canceled)
this.progress = 0; // 0-100
this.response = "{}"; // 上傳完畢後服務器的返回值, 一般應該是一個JSON字符串
this.enableLog = true; // 是否顯示內部打印
// 輸入參數可以是:Selector / jQuery對象 / 原生DOM
this.setButton = function(fileButton)
{
// 如果輸入參數是 Selector
if(fileButton.constructor == String) fileButton = $(fileButton);
// 如果輸入參數是jQuery對象, 則轉成DOM
if(fileButton.constructor == jQuery)
{
if(fileButton.length==0) throw ("你的jQuery選擇器寫錯了!請檢查選擇器!");
fileButton = fileButton[0];
}
// 先看原來有沒有綁定, 如果已經綁定了一個uploader,則返回原有對象
if(fileButton.uploader != null) return fileButton.uploader;
// 創建新的uploader
this.fileButton = fileButton;
// 把上下文存放到DOM元素裏
this.fileButton.uploader = this;
// 添加回調,確保只添加一次
// this.fileButton.removeEventListener("change", this.onFileChanged);
// this.fileButton.addEventListener("change", this.onFileChanged);
this.fileButton.addEventListener("change", function(){
var ctx = this.uploader;
var fileButton = this;
if(fileButton.files.length == 0) return;
var file = fileButton.files[0];
ctx.log("select file: " + file.name);
fileButton.value = ''; // 清空選擇
ctx.setFile(file);
ctx.startUpload( );
});
return this;
};
this.setUploadUrl = function(url)
{
this.uploadUrl = url;
return this;
};
// 事件處理 : 'start' 'progress' 'complete' 'error' 'abort'
this.processEvent = function( event )
{
};
// 是否接受上傳, true:可以上傳; false:不能上傳
this.beforeUpload = function()
{
return true;
};
this.setLogEnabled = function( enabled)
{
this.enableLog = enabled;
return this;
};
// 設置文件 (並不立即啓動)
this.setFile = function(file)
{
this.file = file;
return this;
};
// 打開文件對話框,讓用戶選擇文件
this.openFileDialog = function()
{
if(this.fileButton == null) throw ("尚未初始化file button! 請調用 setButton() 進行設置!");
$(this.fileButton).click();
};
// 外部可以直接送進來一個 File 對象
this.startUpload = function( )
{
if(this.uploadUrl == null) throw ("尚未設置uploadUrl,無法上傳! 請調用 setUploadUrl()進行設置!");
if(this.file == null) throw ("尚未設置file! 請調用openFileDialog()打開文件選擇對話框!或者調用setFile()傳一個File對象!");
var file = this.file;
// 上傳測試: 是否允許上傳
if( ! this.beforeUpload())
{
this.log("不滿足上傳條件 ! " + file.name);
return;
}
this.log("開始上傳: " + file.name);
var formData = new FormData();
formData.append('file', file); // 'file' 爲HTTP Post裏的字段名, file 對瀏覽器裏的File對象
var formRequest = new XMLHttpRequest();
formRequest.ctx = this;
formRequest.upload.ctx = this;
formRequest.upload.addEventListener("progress", this.evt_upload_progress, false);
formRequest.addEventListener("load", this.evt_upload_complete, false);
formRequest.addEventListener("error", this.evt_upload_failed, false);
formRequest.addEventListener("abort", this.evt_upload_cancel, false);
this.processEvent('start');
formRequest.open("POST", this.uploadUrl );
formRequest.send(formData);
this.formRequest = formRequest; /* 保存這個上傳者對象, 用於調用其abort()函數 */
this.status = 1;
return this;
};
// 取消上傳
this.cancelUpload = function()
{
if(this.formRequest != null)
{
try{
this.formRequest.abort();
this.formRequest = null;
this.status = -2;
}catch(err)
{
Af.log("取消上傳時出錯 :" + err);
}
}
};
this.log = function(msg)
{
if(!this.enableLog) return;
try { console.log(msg); } catch (err) {}
};
//////////////////////////////
this.evt_upload_progress = function (evt)
{
var ctx = this.ctx;
if (evt.lengthComputable)
{
ctx.progress = Math.round(evt.loaded * 100 / evt.total);
ctx.log ("上傳進度: " + ctx.progress);
ctx.processEvent('progress');
}
};
this.evt_upload_complete = function (evt)
{
var ctx = this.ctx;
if(evt.loaded == 0)
{
ctx.status = -1;
ctx.log ("上傳失敗!" + ctx.file.name);
ctx.processEvent('error');
}
else
{
ctx.status = 100;
ctx.response = evt.target.responseText;
ctx.log (ctx.response);
ctx.processEvent('complete');
}
};
this.evt_upload_failed = function (evt)
{
var ctx = this.ctx;
ctx.status = -1;
ctx.log ("上傳出錯");
ctx.processEvent('error');
};
this.evt_upload_cancel = function (evt)
{
var ctx = this.ctx;
ctx.status = -2;
ctx.log( "上傳中止!");
ctx.processEvent('abort');
};
}
後端:
package my;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.json.JSONObject;
@WebServlet("/FileUploadService")
public class FileUploadService extends HttpServlet
{
// 文件上傳的臨時目錄
File tmpDir ;
@Override
public void init() throws ServletException
{
File webroot = new File(getServletContext().getRealPath("/"));
tmpDir = new File(webroot, "upload");
tmpDir.mkdirs(); // 上傳進來的文件存放在 WebRoot/upload/ 下
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
JSONObject jresp = new JSONObject();
try
{
Object data = doUpload(request, response);
jresp.put("error", 0);
jresp.put("reason", "OK");
if(data != null)
jresp.put("data", data);
} catch (Exception e)
{
jresp.put("error", -1);
jresp.put("reason", e.getMessage());
}
response.setCharacterEncoding("UTF-8");
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.write(jresp.toString(2));
out.close();
}
private Object doUpload(HttpServletRequest request,
HttpServletResponse response) throws Exception
{
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(!isMultipart)
throw new Exception("請求編碼必須爲: multipart/form-data !");
request.setCharacterEncoding("utf-8");
ServletFileUpload upload = new ServletFileUpload();
AfFileUploadInfo info = new AfFileUploadInfo();
FileItemIterator iter = upload.getItemIterator(request);
while(iter.hasNext())
{
//表單域
FileItemStream item = iter.next();
String fieldName = item.getFieldName();
InputStream fieldStream = item.openStream();
if(item.isFormField())
{
// 普通表單域: 直接讀取值
String fieldValue = Streams.asString(fieldStream, "utf-8");
printLog("表單域:" + fieldName + "=" + fieldValue);
}
else
{
// 生成唯一的文件名
info.realName = item.getName(); // 原始文件名
info.suffix = fileSuffix(info.realName); // 後綴
info.tmpFileName = createTmpFileName(info.suffix); // 服務器臨時文件名
info.tmpFile = new File(tmpDir, info.tmpFileName);
info.fileSize = 0; // 文件大小
printLog("文件上傳開始:" + info.realName + " >> " + info.tmpFile);
// 從FieldStream讀取數據, 保存到目標文件
info.tmpFile.getParentFile().mkdirs();
FileOutputStream fileStream = new FileOutputStream(info.tmpFile);
try{
// 從請求裏讀取文件數據,保存到本地文件
info.fileSize = copy(fieldStream, fileStream);
}finally{
try{ fileStream.close();}catch(Exception e){}
try{ fieldStream.close();}catch(Exception e){}
}
printLog("文件上傳完成:" + info.realName + ", 大小: " + info.fileSize);
}
}
// storePath: /upload/20180817-225649-948CC60AFD374333924DF2F3A049417D.jpg
String storePath = "/upload/" + info.tmpFileName;
// contextPath: /demo1601
String url = getServletContext().getContextPath() + storePath;
JSONObject result = new JSONObject();
result.put("storePath", storePath);
result.put("url", url);
return result;
}
private long copy(InputStream in, OutputStream out) throws Exception
{
long count = 0;
byte[] buf = new byte[8192];
while (true)
{
int n = in.read(buf);
if (n < 0)
break;
if (n == 0)
continue;
out.write(buf, 0, n);
count += n;
}
return count;
}
//////////////////////////////////////////////////
private void printLog(String message)
{
System.out.println(message);
}
// 生成一個唯一的ID
private String createUUID ()
{
String s = UUID.randomUUID().toString();
String s2 = s.substring(0,8)+s.substring(9,13)+s.substring(14,18)+s.substring(19,23)+s.substring(24);
return s2.toUpperCase();
}
// 得到一個保證不重複的臨時文件名
private String createTmpFileName(String suffix)
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
String datestr = sdf.format(new Date());
String name = datestr + "-" + createUUID() + "." + suffix;
return name;
}
// 得到文件的後綴名
public String fileSuffix(String fileName)
{
int p = fileName.lastIndexOf('.');
if(p >= 0)
{
return fileName.substring(p+1).toLowerCase();
}
return "";
}
}
package my;
import java.io.File;
public class AfFileUploadInfo
{
public String realName; //原始文件名
public String suffix; //後綴
public String tmpFileName; //服務器臨時文件名
public File tmpFile;
public long fileSize; //文件大小
}