圖片上傳-下載-刪除等圖片管理的若干經驗總結3-單一業務場景的完整解決方案
這次完整地介紹圖片上傳的完整解決方案,如有bug,後續再補充。
一、圖片表
關鍵欄位
id:資料庫主鍵
bizid:相關業務的id,比如某個專案project的主鍵id
type:相關業務的型別,比如type=1表名這個圖片是某個專案的
status:這個圖片的狀態,0:正常狀態,1:已刪除(現在沒有什麼用,因為圖片是物理刪除的),2:臨時的
圖片物理刪除,是考慮到磁碟空間容易不足。
不應該物理刪除的理由是,今後可能會還原或者其它業務需要。
如果是邏輯刪除,要注意“邏輯刪除”和“臨時上傳的垃圾圖片”物理刪除是需要分開考慮的。
而如果是物理刪除,則可以合併考慮。
二、圖片上傳後端程式碼
1.儲存圖片
2.儲存photo資訊
3.返回新增圖片的id、路徑等資訊給前端
三、前端圖片上傳
1.採用非同步上傳,把一條圖片資訊的id、name等資訊,傳給後端儲存。
2.一次性傳入多個圖
存在“增加”和“刪除”按鈕。
點選增加按鈕,就多生成1個上傳圖片的控制元件。
點選刪除按鈕,就根據id刪除某個圖片上傳空間。
四、圖片儲存
id是所屬專案的id,photos是前端所有圖片的資訊(json格式)
儲存過程:
重寫Photo的equals方法,id相等則相等。
五、寫在最後
1.由於個人喜歡在本地儲存完整的文章,不喜歡圖片,另外CSDN的相簿也不怎麼好用。
我寫的文章很少出現圖片,大家湊合著看。
2.由於圖片管理是完整專案的一部分,不方便上傳完整程式碼。
先記下來,最近抽空,單獨開一個工程,演示圖片上傳。
3.多圖分開上傳,是因為專案中的圖片可以有 備註remark、排序sort等很多欄位。
如果只需要url等少量欄位的話,可以採用百度的WebUploader多圖上傳元件。
4.程式碼中,存在前端jQuery、後端Java程式碼。
5.圖片的物理儲存,可以存到本地,也可以用Fastdfs。
6.過幾天單獨建立多圖演示專案的時候,我打算簡化點,儲存圖片不用Fastdfs。
再單獨搞個專案,演示Fastdfs的用法。
7.有需要的人士,自己參考整合多圖上傳到Fastdfs。
8.多圖上傳,真不是一個簡單的問題,至少花了3個完整的工作日。
一、圖片表
CREATE TABLE `photo` (
`id` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
`bizid` bigint(11) NOT NULL DEFAULT '-1' COMMENT '業務id,比如專案的id',
`cover` int(11) DEFAULT '0' COMMENT '1:是,0:不是',
`sort` int(11) DEFAULT '0' COMMENT '越小越靠前',
`url` varchar(200) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '圖片的原檔名',
`remark` varchar(255) DEFAULT NULL COMMENT '圖片備註',
`status` int(11) DEFAULT '0' COMMENT '0:正常,1:已刪除,2:臨時的',
`type` int(11) DEFAULT '1' COMMENT '1:專案資料 2:待續',
`addtime` datetime DEFAULT NULL,
`uptime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8 COMMENT='使用者上傳的圖片';
關鍵欄位
id:資料庫主鍵
bizid:相關業務的id,比如某個專案project的主鍵id
type:相關業務的型別,比如type=1表名這個圖片是某個專案的
status:這個圖片的狀態,0:正常狀態,1:已刪除(現在沒有什麼用,因為圖片是物理刪除的),2:臨時的
圖片物理刪除,是考慮到磁碟空間容易不足。
不應該物理刪除的理由是,今後可能會還原或者其它業務需要。
如果是邏輯刪除,要注意“邏輯刪除”和“臨時上傳的垃圾圖片”物理刪除是需要分開考慮的。
而如果是物理刪除,則可以合併考慮。
二、圖片上傳後端程式碼
@RequestMapping("uploadImg")
public void uploadImg(MultipartHttpServletRequest request,
HttpServletResponse response, Long bizid,Integer type) {
MultipartFile file = request.getFile("file");
MultipartFileValidator validator = new MultipartFileValidator();
validator.setAllowedContentTypes(new String[] { "image/jpeg",
"image/pjpeg", "image/png", "image/x-png" });
String path = null;
String name = null;
try {
if (null != file && !file.isEmpty()) {
name = file.getOriginalFilename();
validator.validate(file);
path = storeFile(file);
storeSlaveFile(file, path);
} else {
throw new Exception("file is empty");
}
} catch (Exception e) {
e.printStackTrace();
super.jsonFail(response, "圖片格式不正確或大小超過1M");
return;
}
Long id = null;
if (bizid != null) {
// 臨時圖片存起來
Photo photo = new Photo();
photo.setName(name);
photo.setUrl(path);
photo.setBizid(bizid);
photo.setStatus(2);
photo.setType(type);
id = photoService.add(photo);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", ErrorCode.OK.getCode());
jsonObject.put("path", path);
jsonObject.put("name", name);
if (id != null) {
jsonObject.put("id", id);
}
super.returnJsonObject(response, jsonObject);
}
1.儲存圖片
2.儲存photo資訊
3.返回新增圖片的id、路徑等資訊給前端
三、前端圖片上傳
function bindSaveEvent(){
console.log("bindSaveEvent");
$("#save").on("click", function() {
var trs=$(".tr");
var photos = new Array();
$.each(trs,function(i,n){
var tr = $(trs[i]);
var photo ={};
//newid是資料庫中的id
var id=tr.attr("id");
var newid=tr.attr("newid");
photo.id=newid;
photo.cover=$("#"+id+"-cover").val();
photo.sort=$("#"+id+"-sort").val();
photo.remark=$("#"+id+"-remark").val();
photo.url=$("#"+id+"-img").attr("path");
photo.name=$("#"+id+"-name").val();
console.log("id="+id);
photos[i]=photo;
});
var json=JSON.stringify(photos);
console.log("id=${photoVo.project.id}"+",photos="+json);
$.ajax( {
url:'project/savePhoto',
data:{
id : ${photoVo.project.id},
photos: json
},
type:'post',
cache:false,
async: true,
dataType:'json',
success:function(data) {
//alert(data.itemName);
//nameStr = data.itemName;
console.log("data="+data);
},
error : function() {
alert("儲存圖片失敗!");
}
});
});
}
1.採用非同步上傳,把一條圖片資訊的id、name等資訊,傳給後端儲存。
2.一次性傳入多個圖
存在“增加”和“刪除”按鈕。
function bindAddEvent(){
console.log("bindAddEvent");
$("#add").on("click", function() {
var strTemplate=
'<tr id="{photo.id}" newid="" class="tr">'+
'<td><input id="{photo.id}-name" type="text" value="" /></td>'+
'<td><select id="{photo.id}-sort" class="sort">'+
'<option value="1">1</option>'+
'<option value="2">2</option>'+
'<option value="3">3</option>'+
'<option value="4">4</option>'+
'<option value="5">5</option>'+
'<option value="6">6</option>'+
'<option value="7">7</option>'+
'<option value="8">8</option>'+
'<option value="9">9</option>'+
'<option value="10">10</option>'+
'<option value="0">0</option>'+
'</select></td>'+
'<td><select id="{photo.id}-cover" owner="{photo.id}"'+
'class="cover">'+
'<option value="0">否</option>'+
'<option value="1">是</option>'+
'</select></td>'+
'<td><input type="text" id="{photo.id}-remark" value="" /></td>'+
'<td><input type="file" id="{photo.id}-file" name="file"'+
'style="width: 264px" onchange="uploadImg({photo.id});"><img'+
' id="{photo.id}-img" src="" path=""'+
' width="80%"></td>'+
'<td><a id="{photo.id}-del" owner="{photo.id}"'+
'href="javascript:;" class="del">刪除</a></td>'+
'</tr>';
var photoId = new Date().getTime();
var html = strTemplate.replace(/{photo.id}/g,photoId);
var tbody = $("#tbody");
tbody.append(html);
console.log(html);
//必須為新生成的物件,重新繫結事件
bindDelEvent();
bindCoverChangeEvent();
});
}
點選增加按鈕,就多生成1個上傳圖片的控制元件。
點選刪除按鈕,就根據id刪除某個圖片上傳空間。
四、圖片儲存
public void savePhoto(HttpServletResponse response, @RequestParam Long id,String photos) {
List<Photo> list=JSONArray.parseArray(photos, Photo.class);
projectService.savePhoto(id,list);
super.jsonSucceed(response);
}
id是所屬專案的id,photos是前端所有圖片的資訊(json格式)
儲存過程:
public void savePhoto(Long id, List<Photo> list) {
if (CollectionUtils.isEmpty(list)) {
logger.error("The photo list is empty~");
return;
}
// 這個專案資料庫中的圖片,包括所有的狀態
List<Photo> dbList = photoDao.getPhotoListByProjectIdAllStatus(id);
PhotoBean photoBean = handlePhoto(list, dbList);
//理論上,不再存在add doAdd(id, photoBean.toAdd);
doUpdate(id, photoBean.toUpdate);
doDelete(id, photoBean.toDelete);
}
doUpdate和doDelete批量更新和批量刪除方法,很清晰,不再贅述。
//PhotoBean的結構
class PhotoBean {
//將要刪除的,通常是資料庫中的
public List<Photo> toDelete;
//將要更新的,都在資料庫中,部分最新內容來源於web前端
public List<Photo> toUpdate;
//將要增加的,由於上傳圖片的時候都已經插入了,這個時候可以忽略了
//public List<Photo> toAdd;
}
//根據前端photo集合和資料庫photo集合,得到需要更新和需要刪除的photo集合,不存在需要增加的photo集合
private PhotoBean handlePhoto(List<Photo> list, List<Photo> dbList) {
PhotoBean bean = new PhotoBean();
// 全部刪除,什麼圖片都沒有上傳
if (CollectionUtils.isEmpty(list)) {
bean.toDelete = dbList;
}
// 全部增加,一般在第1次
/* if (CollectionUtils.isEmpty(dbList)) {
bean.toAdd = list;
}*/
// 都不為null
if (list != null && dbList != null) {
// 交集,肯定不為null,最多是empty,id相同就是共同存在
List<Photo> commonList = ListUtils.retainAll(list, dbList);
// 2者交集
List<Photo> toUpdate = commonList;
//資料庫中的臨時圖片,狀態需要改為“正常”
if(CollectionUtils.isNotEmpty(toUpdate)){
for(Photo p:toUpdate){
p.setStatus(0);
}
}
// 在list,不再dbList中的
/* List<Photo> toAdd = new ArrayList<Photo>();
for (Photo p : list) {
if (!dbList.contains(p)) {
toAdd.add(p);
}
}*/
// 在dbList,不在list中的
List<Photo> toDelete = new ArrayList<Photo>();
for (Photo p : dbList) {
if (!list.contains(p)) {
toDelete.add(p);
}
}
//bean.toAdd=toAdd;
bean.toUpdate=toUpdate;
bean.toDelete=toDelete;
}
return bean;
}
重寫Photo的equals方法,id相等則相等。
五、寫在最後
1.由於個人喜歡在本地儲存完整的文章,不喜歡圖片,另外CSDN的相簿也不怎麼好用。
我寫的文章很少出現圖片,大家湊合著看。
2.由於圖片管理是完整專案的一部分,不方便上傳完整程式碼。
先記下來,最近抽空,單獨開一個工程,演示圖片上傳。
3.多圖分開上傳,是因為專案中的圖片可以有 備註remark、排序sort等很多欄位。
如果只需要url等少量欄位的話,可以採用百度的WebUploader多圖上傳元件。
4.程式碼中,存在前端jQuery、後端Java程式碼。
5.圖片的物理儲存,可以存到本地,也可以用Fastdfs。
6.過幾天單獨建立多圖演示專案的時候,我打算簡化點,儲存圖片不用Fastdfs。
再單獨搞個專案,演示Fastdfs的用法。
7.有需要的人士,自己參考整合多圖上傳到Fastdfs。
8.多圖上傳,真不是一個簡單的問題,至少花了3個完整的工作日。
相關文章
- 圖片上傳-下載-刪除等圖片管理的若干經驗總結
- 圖片上傳-下載-刪除等圖片管理的若干經驗總結2
- 基於業務場景下的圖片/檔案上傳方案總結
- 道歉,上傳的檔案或圖片等資料被刪除
- 圖片上傳方案詳解
- java,springboot + thymeleaf 上傳圖片、刪除圖片到伺服器、本地,壓縮圖片上傳(有些圖片會失真),原圖上傳JavaSpring Boot伺服器
- elementUI中form表單的upload上傳圖片及校驗總結UIORM
- 移動端圖片上傳旋轉、壓縮的解決方案
- 44. JS 應用場景(Promise => 圖片上傳)JSPromise
- javascript圖片上傳格式尺寸等特徵驗證效果JavaScript特徵
- 前端圖片解決方案前端
- 圖片上傳及圖片處理
- koa 圖片上傳詳解
- IE8.0 上傳圖片時,提示無效的圖片檔案的解決辦法!
- 圖片載入失敗解決方案 以及canvas即時生成提示圖片Canvas
- 直播系統搭建,插入圖片、刪除圖片、設定圖片大小
- php圖片上傳之圖片轉換PHP
- curl上傳圖片的大坑
- Retrofit+RxJava上傳圖片上傳圖片到後臺RxJava
- 新聞管理軟體的完美圖片解決方案 (轉)
- 織夢dedecms圖片集上傳圖片不能上傳 彈出提示302的解決方法
- 【easyui 】上傳圖片UI
- 上傳圖片jsJS
- kindeditor 圖片管理增加刪除操作按鈕
- php 非同步上傳圖片幾種方法總結PHP非同步
- 使用 canvas 繪製圖片,然後下載、上傳Canvas
- 菜鳥學JS(一)——上傳圖片之上傳前預覽圖片JS
- js封裝,常用ajax刪除和手機驗證,上傳圖片的方法,基於layerJS封裝
- [python][flask] Flask 圖片上傳與下載例子(支援漂亮的拖拽上傳)PythonFlask
- vue 上傳圖片進行壓縮圖片Vue
- JS—圖片壓縮上傳(單張)JS
- VUE + UEditor 單圖片跨域上傳Vue跨域
- [文件教程]解決sae下編輯器圖片上傳問題
- Excel 刪除圖片小技巧Excel
- ci框架中的圖片上傳框架
- mino如何上傳同名的圖片
- Nginx圖片下載不完整的處理過程Nginx
- Excel怎麼批次刪除表格中的圖片?Excel一次性刪除表格中所有圖片教程Excel