express中用mongoose操作資料庫-儲存圖片、修改資料(四)
阿新 • • 發佈:2019-01-28
從專案的角度上來說,圖片儲存和資料庫儲存都是必須要分離的,否則這一個模組就能拖垮你的整個工程。 二進位制的儲存方式,已經淘汰了,效能非常差,在以後的資料庫版本里已經取消了這個儲存方式。存放路徑,是一種非常方便的解決方案,不存在什麼其他的問題,容易管理。比如,你以前用二進位制儲存的一個圖片,又要IO又要快取的才能展示給使用者看。現在你儲存的是地址,僅僅需要把連結提取出來即可,這樣減少了資料訪問上的壓力。
所以要先將圖片檔案上傳到伺服器,,再往資料庫中存圖片檔案的路徑,怎麼傳二進位制檔案呢?form表單可以,但是不是非同步的,ajax是非同步的,但是要xhr2才支援傳二進位制檔案,所以這裡用H5支援的一個物件FormData,相當於模擬一個表單提交將圖片傳至伺服器,當然還是要用到一個外掛,formidable,具體流程:
a:cnpm i --save formidable 安裝外掛,安裝好後,它還需要一個配置模組:
b,前端往伺服器儲存:var cacheFolder = 'uploadcache/';//存放圖片的檔名稱 exports.upload = function(req, res) { var fs = require('fs'); var formidable = require('formidable'); //var currentUser = req.session.username; // var userDirPath =cacheFolder /*+ currentUser;*/ if (!fs.existsSync(userDirPath)) { fs.mkdirSync(userDirPath); } var form = new formidable.IncomingForm(); //建立上傳表單 form.encoding = 'utf-8'; //設定編輯 form.uploadDir = userDirPath; //設定上傳目錄 form.keepExtensions = true; //保留後綴 form.maxFieldsSize = 2 * 1024 * 1024; //檔案大小 form.type = true; var displayUrl; form.parse(req, function(err, fields, files) { if (err) { res.send(err); return; } var extName = ''; //字尾名 switch (files.upload.type) { case 'image/pjpeg': extName = 'jpg'; break; case 'image/jpeg': extName = 'jpg'; break; case 'image/png': extName = 'png'; break; case 'image/x-png': extName = 'png'; break; } if (extName.length === 0) { res.send({ code: 202, msg: '只支援png和jpg格式圖片' }); return; } else { var avatarName = '/' + Date.now() + '.' + extName; var newPath = form.uploadDir + avatarName; displayUrl = /*currentUser +*/ avatarName; fs.renameSync(files.upload.path, newPath); //重新命名 res.json({ code: 0, img: displayUrl }); } }); };
c.前端上傳完圖片,填寫完評論內容後提交評論(將圖片路徑,評論詳情儲存到資料庫),並且收到了後端返回的提交的資料,再次呼叫模板引擎往html中append這條評論://圖片上傳 var $imgFile = $(".submit .img input[type=file]"); $imgFile.change(function(){ var type = this.files[0].type; if(type === "image/png" || type === "image/jpeg"){ var form = new FormData();//H5的物件 form.append("upload", this.files[0]);//第一個引數代表封裝的這個物件的key,跟後臺協商; //非同步上傳圖片物件 $.ajax({ url: "/upload", type: "POST", dataType:"json", data: form, contentType: false, //傳送資訊到伺服器的內容型別 告訴jq不要去設定Content-Type請求頭,預設是 application/x-www-form-urlencoded (form型別) processData: false, //processData 是jq 獨有的引數 用於對data引數進行序列化處理,預設值是true, //所謂序列化 就是比如{ width:1680, height:1050 }引數物件序列化為width=1680&height=1050這樣的字串。 }).done(function(res){ if(!res.code){ $("#img").attr("src", res.img);//顯示預覽圖,到時往資料庫儲存圖片路徑時就在這個圖片上獲取就可以了 } }) } })
//評論提交
var $tit = $("#tit"), $con = $("#con"), $img = $("#img"), $sbt = $("#sbt");
$sbt.click(function(){
var params = {
title: $tit.val(),
content: $con.val(),
img: $img.attr("src"),
author: u
};
if(!params.title || !params.content){
alert("不能為空!");
return;
};
$.post("/sbtComment", params, function(data){
if(!data.code){
if($("h2.empty").is(":visible")){
$("h2.empty").hide();
}
var html = template("commentList", data);
$list.append(html);
$tit.val("");
$con.val("");
$img.attr("src", "");
}
})
})
這是後端的處理://評論提交
app.post("/sbtComment", function(req, res){
var comment = new Comment(req.body);
comment.save(function(err, doc){//這個doc就是儲存的物件
if(err){return};
res.json({
code: 0,
list: [doc]
})
})
})
d.修改評論,前端類似的操作://評論修改
var $xtit = $("#xtit"), $xcon = $("#xcon"), $ximg = $("#ximg"), $xsave = $("#xsave");
$list.on("click", ".btn-warning", function(){//點選修改彈出模態框同時獲取原內容
$xsave.data("id", $(this).data("id"));//將點選的這條評論的id用自定義屬性儲存到模態框確認按鈕上
$xtit.val($(this).parent().prev(".col-md-10").children("h4").text());
$xcon.val($(this).parent().prev(".col-md-10").children("p").text());
$ximg.attr("src", $(this).parent().prev(".col-md-10").find("img").attr("src"));
})
$(".modal-body .ximg input[type=file]").change(function(){//修改圖片
var type = this.files[0].type;
if(type === "image/png" || type === "image/jpeg"){
var form = new FormData();//H5的物件
form.append("upload", this.files[0]);//第一個引數代表封裝的這個物件的key,跟後臺協商;
//非同步上傳圖片物件
$.ajax({
url: "/upload",
type: "POST",
dataType:"json",
data: form,
contentType: false, //傳送資訊到伺服器的內容型別 告訴jq不要去設定Content-Type請求頭,預設是 application/x-www-form-urlencoded (form型別)
processData: false, //processData 是jq 獨有的引數 用於對data引數進行序列化處理,預設值是true,
//所謂序列化 就是比如{ width:1680, height:1050 }引數物件序列化為width=1680&height=1050這樣的字串。
}).done(function(res){
if(!res.code){
$ximg.attr("src", res.img);
}
})
}
})
$xsave.click(function(){//儲存修改
var params = {
title: $xtit.val(),
content: $xcon.val(),
img: $ximg.attr("src"),
_id: $(this).data("id")
};
if(!params.title || !params.content){
alert("不能為空!");
return;
};
$.post("/modifyComment", params, (data)=>{
if(!data.code){
var html = template("commentList", data);
$(".list-group").find("input[data-id="+$(this).data("id")+"]").parents(".list-group").replaceWith(html);
$('#myModal').modal('hide');//關閉模態框
}
});
})
後端的處理://評論修改
app.post("/modifyComment", function(req, res){
let {_id, title, content, img} = req.body;
//引數3:new取布林值,true表示返回修改的這個物件,
Comment.findOneAndUpdate({_id}, {title, content, img}, {new: true}, function(err, doc){
if(err){return};
res.json({
code: 0,
list: [doc]
})
})
})
到這裡利用前端開發框架express結合mongoose對mongodb資料庫的增刪改查已經熟悉了