最近開發的項目中,有需要對上傳的圖檔進行二次截圖,然後再上傳的功能,本人使用的是jquery的imgareaselect插件進行的截圖。
在詳細介紹如何使用之前,先講一下進行截圖的思路:先将本地的圖檔上傳至資源伺服器,然後将資源伺服器上的圖檔下載下傳至項目中,對下載下傳的圖檔進行切割,将切割好的圖檔上傳至資源伺服器并删除下載下傳到項目中的原圖。其實可以直接将本地的圖檔下載下傳到項目中,但是本地圖檔的位址不太好拿,上傳到資源伺服器以後位址就好拿了,至于為什麼不直接切割遠端的圖檔,直接從遠端切割圖檔切割不了,隻能下載下傳到本地項目了。

還有一點需要注意:從資源伺服器下載下傳到項目中的圖檔,在頁面展示的時候可能由于整體樣式問題,會在頁面被壓縮,你在該頁面上截圖以後,會在後進行同比例的計算。例如一個圖檔是700*500的,但是由于頁面樣式問題,展示是圖檔最大350*350,由于這裡高是700,寬是500,被壓縮以後展示的圖檔就是高350,寬進行等比壓縮就是250,變成350*250的圖,然後在該圖上進行截圖,我們在背景原圖(700*500的圖)上會進行等比計算,計算出在原圖上應該是什麼位置,多寬多高。
下面就是代碼展示了:
首先是相關插件的導入了(插件我上傳到我csdn資源上了,有需要的可以下載下傳):
https://download.csdn.net/download/xiaoye319/10926138
接着就是在頁面上的具體代碼(我這個是jsp頁面):有一塊内容展示的是
<!-- 截圖 -->
<link href="${ctxStatic}/jquery.imgareaselect-0.9.10/css/imgareaselect-default.css" target="_blank" rel="external nofollow" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="${ctxStatic}/jquery.imgareaselect-0.9.10/scripts/jquery.imgareaselect.min.js"></script>
<script type="text/javascript" src="${ctxStatic}/jquery.imgareaselect-0.9.10/scripts/jquery.imgareaselect.pack.js"></script>
從本地上傳圖檔的按鈕,然後還有隐藏一塊内容,用來展示從上傳到資源伺服器的原圖,就是在這塊内容上進行截圖。
<%--上傳店内圖檔--%>
<div class="form-ctrl clearfix">
<div class="form-item desc" style="width: 100%;">
<label>店内圖檔:</label>
<div class="upArea" id="goodsDetailsImages">
<c:if test="${fn:length(office.officeInfo.wxShopImgList) > 0}">
<c:forEach items="${office.officeInfo.wxShopImgList}" var="shopImg">
<div class="imgs" id="wxImg">
<img src="${shopImg}" alt=""/>
<input type="hidden" id="wxShopImgList" name="wxShopImgList" value="${shopImg}">
</div>
</c:forEach>
</c:if>
<div class="upBtn" id="uploadLists"><input type="file" accept="image/png,image/gif,image/jpeg,image/bmp, image/mbm" class="upGoodImg"></div>
</div>
<div class="upload-img-btn" id="shopPhoto">
<span class="upload-btn" onclick="addUpGoodImg()">添加圖檔</span><span class="prompt" style="color: red">建議上傳不少于3張,最多可傳9張圖檔格式為jpg,png,每張大小不超過1M,數量3的倍數為最佳</span>
</div>
</div>
</div>
<!-- 截圖彈出框 -->
<div class="filter-cover-wrap" id="add-rorder-cover">
<div class="filter-contener">
<div class="tree-wrap">
<div class="tree-top">裁剪照片<span class="close-btn" onclick="closeCutPhoto()"></span></div>
<div class="tree-content">
<div style="width: 350px;height: 350px;line-height:350px;text-align:center; margin: 0 auto">
<img alt="" src="" style="max-width: 350px;max-height: 350px;border: 1px solid black;" id="cutphoto">
<input id="x1" name="x1" type="hidden">
<input id="y1" name="y1" type="hidden">
<input id="width" name="width" type="hidden">
<input id="height" name="height" type="hidden">
</div>
</div>
<div class="tree-bottom">
<button type="button" class="sure-btn" onclick="cutPhoto()">确定</button>
</div>
</div>
</div>
</div>
接下來就是js部分了,上傳本地圖檔到資源伺服器上,傳回url到截圖展示區域展示,然後截圖到背景:
//添加圖檔
function addUpGoodImg() {
$('.upGoodImg').click()
}
// 上傳店内圖檔
function upGoodImg (elem) {
var formData = new FormData(),
file = elem[0],
fileSize = file.files[0].size;
if ( Math.round(fileSize/1024)/1000 > 1 ) {
$.JsDialog.Alert("提示", '圖示過大上傳會失敗!');
return
}
formData.append('file', file.files[0]);
$.ajax({
type: 'post',
url: newUploadURL,
contentType: false, //這個一定要寫
processData: false, //這個也一定要寫,不然會報錯
data:formData,
dataType:'json', //傳回類型,有json,text,HTML。這裡并沒有jsonp格式,是以别妄想能用jsonp做跨域了。
beforeSend: function () {
$('.page-loading').show()
}, success:function(data){
$("#x1,#y1,#width,#height").val("");
$("#cutphoto").attr("src",data.file_url);
$("#add-rorder-cover").addClass('show');
cutImg("1:1");
$('.page-loading').hide()
}, error: function(XMLHttpRequest, textStatus, errorThrown, data){
$.JsDialog.Alert('上傳失敗,請稍後重試.')
}
})
}
// 截取照片方法
function cutImg(s){
$('#cutphoto').imgAreaSelect({
aspectRatio: s,
onSelectEnd: function (img, selection) {
$('input[name="x1"]').val(selection.x1);
$('input[name="y1"]').val(selection.y1);
$('input[name="width"]').val(selection.width);
$('input[name="height"]').val(selection.height);
}
});
}
// 确定截取照片
function cutPhoto(){
if($("#x1").val().length > 0 && $("#y1").val().length > 0 && $("#width").val().length > 0 && $("#height").val().length > 0){
$(".loading").show();
$.ajax({
type : "POST",
url : "${ctx}/sys/office/ajaxCutImg",
data:{'path':$("#cutphoto").attr("src"),'x':$("#x1").val(),'y':$("#y1").val(),'width':$("#width").val(),'height':$("#height").val()},
dataType: 'text',
success: function(str) {
$(".loading").hide();//隐藏展示層
closeCutPhoto();
var data = $.parseJSON(str);
console.log(data)
if(data.status == 200){
$("#goodsDetailsImages").before().append('<div class="imgs" id="wxImg">'
+'<img src="' + data.msg.file_url +'" alt="" style="width: 200px;hight:200px"><input type="hidden" name="wxShopImgList" value="' + data.msg.file_url +'">'
+'</div>');
$("#uploadLists").hide();
$('.upGoodImg').val('')
}else{
top.layer.alert('截圖出現異常!', {icon: 0});
}
},
error:function(data){
top.layer.alert('截圖出現異常!', {icon: 0});
}
});
}else{
top.layer.alert('未截取圖檔!請重新截取!', {icon: 0});
}
}
// 關閉截圖彈出框
function closeCutPhoto(){
$('#cutphoto').imgAreaSelect({
remove:true
});
$("#add-rorder-cover").removeClass('show');
}
其中cutImg()方法是設定截圖的比例,設定為1:1或者1:2等,若不傳入參數,則代表自由截取;cutPhoto()方法是在頁面選取好想要截取的圖檔以後請求背景在原圖上進行計算,成功以後上傳到資源伺服器,然後傳回截取後的圖檔在資源伺服器上的位址。
下面是背景計算方法:
/**
* 截圖
* @param path
* @param x
* @param y
* @param width
* @param height
* @param request
* @return
*/
@ResponseBody
@SuppressWarnings("null")
@RequestMapping(value = "ajaxCutImg")
public String ajaxCutImg(String path,int x,int y,int width,int height,HttpServletRequest request){
JSONObject josn = new JSONObject();
JSONObject josnIO = new JSONObject();
try {
// 下載下傳照片到本地
josnIO = convertIO(path,request,logger);
if("200".equals(josnIO.get("status"))){
// 截圖儲存到本地
String string = cutImg(josnIO.get("msg").toString(), x, y, width, height,request,logger);
if("true".equals(string)){
// 上傳本地照片到伺服器
josn = postImg(josnIO.get("msg").toString(),request,logger);
}else{
josn.put("status", "-1");
josn.put("msg","截圖出現異常,請聯系管理者");
}
}else{
josn.put("status", "-1");
josn.put("msg","截圖出現異常,請聯系管理者");
}
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截圖出現異常", e);
logger.error("截圖錯誤資訊:"+e.getMessage());
josn.put("status", "-1");
josn.put("msg","截圖出現異常,請聯系管理者");
return josn.toString();
}
boolean success = (new File(josnIO.get("msg").toString())).delete();
if (success) {
System.out.println("删除本地照片成功: " + josnIO.get("msg").toString());
} else {
System.out.println("删除本地照片失敗: " + josnIO.get("msg").toString());
}
System.out.println(josn.get("msg"));
return josn.toString();
}
// 下載下傳圖檔到本地
public JSONObject convertIO(String path,HttpServletRequest request,org.slf4j.Logger logger){
// 傳回結果集
JSONObject josn = new JSONObject();
try {
//new一個URL對象
URL url = new URL(path);
//打開連結
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//設定請求方式為"GET"
conn.setRequestMethod("GET");
//逾時響應時間為5秒
conn.setConnectTimeout(5 * 1000);
//通過輸入流擷取圖檔資料
InputStream inStream = conn.getInputStream();
//得到圖檔的二進制資料,以二進制封裝得到資料,具有通用性
byte[] data = readInputStream(inStream);
// 截取原照片字尾
String string = path.substring(path.lastIndexOf(".") + 1);
TrainRuleParam trainRuleParam =new TrainRuleParam();
trainRuleParam.setParamKey("excel_path");
//本地項目位址:
//String newURL = "E:/XXX/src/main/webapp/static/cutImg/down_"+new java.util.Date().getTime()+"_photo."+string;
//線上項目在tomcat的位址
String newURL = ParametersFactory.getMtmyParamValues("pc_project_root_path") + "/static/cutImg/down_"+new java.util.Date().getTime()+"_photo."+string;
//new一個檔案對象用來儲存圖檔,預設儲存目前工程根目錄
File imageFile = new File(newURL);
//建立輸出流
FileOutputStream outStream = new FileOutputStream(imageFile);
//寫入資料
outStream.write(data);
//關閉輸出流
outStream.close();
josn.put("status", "200");
josn.put("msg",newURL);
return josn;
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截圖上傳--下載下傳圖檔到本地出現異常", e);
logger.error("截圖上傳--下載下傳圖檔到本地錯誤資訊:"+e.getMessage());
josn.put("status", "-1");
josn.put("msg","截圖出現異常,請聯系管理者");
return josn;
}
}
public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//建立一個Buffer字元串
byte[] buffer = new byte[1024];
//每次讀取的字元串長度,如果為-1,代表全部讀取完畢
int len = 0;
//使用一個輸入流從buffer裡把資料讀取出來
while( (len=inStream.read(buffer)) != -1 ){
//用輸出流往buffer裡寫入資料,中間參數代表從哪個位置開始讀,len代表讀取的長度
outStream.write(buffer, 0, len);
}
//關閉輸入流
inStream.close();
//把outStream裡的資料寫入記憶體
return outStream.toByteArray();
}
public static String cutImg(String srcImageFile, int x, int y, int destWidth, int destHeight,HttpServletRequest request,org.slf4j.Logger logger) {
try {
Image img;
ImageFilter cropFilter;
// 讀取源圖像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getWidth(); // 源圖寬度
int srcHeight = bi.getHeight(); // 源圖高度
logger.info("#######照片原始寬度srcWidth= " + srcWidth + "_____原始高度srcHeight= " + srcHeight);
double scale = 1;
if(srcWidth >= 350 && srcHeight >= 350){
if(srcWidth >= srcHeight){
scale = (double)srcWidth/(double)350;
}else if(srcWidth < srcHeight){
scale = (double)srcHeight/(double)350;
}else{
scale = 0;
}
}else if(srcWidth > 350 && srcHeight <= 350){
scale = (double)srcWidth/(double)350;
}else if(srcHeight > 350 && srcWidth <= 350){
scale = (double)srcHeight/(double)350;
}else{
scale = 1;
}
x = (int)(x*scale);
y = (int)(y*scale);
destWidth = (int)(destWidth*scale);
destHeight = (int)(destHeight*scale);
if (srcWidth >= destWidth && srcHeight >= destHeight) {
Image image = bi.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
// 改進的想法:是否可用多線程加快切割速度
// 四個參數分别為圖像起點坐标和寬高
// 即: CropImageFilter(int x,int y,int width,int height)
cropFilter = new CropImageFilter(x, y, destWidth, destHeight);
img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(destWidth, destHeight,BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, null); // 繪制縮小後的圖
g.dispose();
// 截取原照片字尾
String string = srcImageFile.substring(srcImageFile.lastIndexOf(".") + 1);
// 輸出為檔案 覆寫原檔案
ImageIO.write(tag, string, new File(srcImageFile));
return "true";
}
} catch (Exception e) {
BugLogUtils.saveBugLog(request, "截圖上傳--截圖出現異常", e);
logger.error("截圖上傳--截圖錯誤資訊:"+e.getMessage());
return "false";
}
return "false";
}
// 上傳本地照片到伺服器
public static JSONObject postImg(String newURL,HttpServletRequest request,org.slf4j.Logger logger) {
HttpClient client = new HttpClient();
// 傳回結果集
JSONObject resJson = new JSONObject();
try {
PostMethod postMethod = new PostMethod(ParametersFactory.getMtmyParamValues("uploader_url"));
// FilePart:用來上傳檔案的類
FilePart filePart = new FilePart("img", new File(newURL));
Part[] parts = {
filePart
};
// 對于MIME類型的請求,httpclient建議全用MulitPartRequestEntity進行包裝
MultipartRequestEntity mre = new MultipartRequestEntity(parts, postMethod.getParams());
postMethod.setRequestEntity(mre);
// 執行請求,傳回狀态碼
int status = client.executeMethod(postMethod);
if (status == HttpStatus.SC_OK) {
System.out.println("上傳到伺服器請求成功,傳回資訊:" + postMethod.getResponseBodyAsString());
resJson.put("status", "200");
resJson.put("msg",postMethod.getResponseBodyAsString());
return resJson;
} else {
System.out.println("請求上傳圖檔,請求失敗。");
resJson.put("status", "-1");
resJson.put("msg", "上傳圖檔,請求失敗。");
return resJson;
}
} catch(Exception e) {
resJson.put("status", "-1");
resJson.put("msg", "系統異常");
System.out.println("請求上傳圖檔,請求失敗。"+e.toString());
return resJson;
}
}
以上就是使用jquery的imgareaselect插件進行截圖的全部過程,有問題請及時溝通