最後,關于顯示分頁,首先要使得以前加載資料的函數是支援頁碼參數的:
loadMyQuestions: function (page) {
if (!page || page < 1) {
page = 1;
}
$.ajax({
url: '/api/v1/questions/my',
data: 'page=' + page,
// 省略後續代碼
});
}
關于分頁的頁面部分的代碼:
<nav aria-label="Page navigation example">
<div class="pagination">
<a class="page-item page-link" href="#"
v-on:click.prevent="loadMyQuestions(pageInfo.prePage)">上一頁</a>
<a class="page-item page-link " href="#"
v-for="i in pageInfo.navigatepageNums"
v-on:click.prevent="loadMyQuestions(i)"
v-bind:class="{ 'bg-primary text-light': i == pageInfo.pageNum }">
<span v-text="i">1</span>
</a>
<a class="page-item page-link" href="#"
v-on:click.prevent="loadMyQuestions(pageInfo.nextPage)">下一頁</a>
</div>
</nav>
在my.js中,在屬性中聲明pageInfo:
data: {
questions: [],
pageInfo: null
}
當擷取資料後,添加:
questionsApp.pageInfo = data;
至此,頁面的顯示已完成,關于my.js的完整代碼:
let questionsApp = new Vue({
el: '#questionsApp',
data: {
questions: [
{
statusText: '已解決',
statusClass: 'badge-success',
title: '這是第1個問題',
content: '很<b>嚴肅</b>的提出了第1個問題',
tags: [
{ id: 8, name: 'Java基礎' },
{ id: 12, name: 'Spring' },
{ id: 15, name: 'SpringBoot' }
],
userNickName: '天下第一',
hits: '826',
createdTimeText: '8小時之前',
tagImage: '/img/tags/8.jpg'
},
{
statusText: '未回複',
statusClass: 'badge-warning',
title: '這是第2個問題',
content: '我也不告訴你是什麼問題……',
tags: [
{ id: 10, name: 'MySQL' },
{ id: 17, name: 'SpringSecurity' }
],
userNickName: '天下第一',
hits: '537',
createdTimeText: '15小時之前',
tagImage: '/img/tags/10.jpg'
}
],
pageInfo: null
},
methods: {
loadMyQuestions: function (page) {
if (!page || page < 1) {
page = 1;
}
$.ajax({
url: '/api/v1/questions/my',
data: 'page=' + page,
success: function (json) {
// json.data.list
let data = json.data;
let questions = data.list;
let statusTexts = ['未回複', '未解決', '已解決'];
let statusClasses = ['badge-warning', 'badge-info', 'badge-success'];
for (let i = 0; i < questions.length; i++) {
questions[i].statusText = statusTexts[questions[i].status];
questions[i].statusClass = statusClasses[questions[i].status];
questions[i].tagImage = '/img/tags/' + questions[i].tags[0].id + '.jpg';
let now = new Date().getTime();
let pastTime = (now - new Date(questions[i].createdTime).getTime()) / 1000;
let createdTimeText = "未知時間";
if (pastTime < 60) { // 不足1分鐘
createdTimeText = "剛剛";
} else if (pastTime < 60 * 60) { // 不足1小時
createdTimeText = parseInt(pastTime / 60) + "分鐘前";
} else if (pastTime < 60 * 60 * 24) {
createdTimeText = parseInt(pastTime / 60 / 60) + "小時前";
} else {
createdTimeText = parseInt(pastTime / 60 / 60 / 24) + "天前";
}
questions[i].createdTimeText = createdTimeText;
}
questionsApp.questions = questions;
questionsApp.pageInfo = data;
}
});
}
},
created: function () {
this.loadMyQuestions();
}
});
46. 關于Summernote的圖檔處理
使用Summernote富文本編輯器時,當需要處理圖檔時,會自動将圖檔轉換為Base64編碼,當送出問題時,圖檔的Base64編碼會作為“問題正文”的一部分送出到伺服器端,最終,會被存儲到資料庫中!使用這種做法,會急劇增加資料庫所占用的存儲空間,對資料庫的檢索性能也會産生影響,不利于資料庫的管理和維護,同時,由于圖檔已經轉換為Base64編碼作為正文的一部分資料,也不利于管理圖檔!
Summernote允許在配置Summernote富文本編輯器時自定義回調函數,該函數會在使用者填寫正文時選擇圖檔會自動調用,則開發人員可以配置這個回調函數,當使用者選擇圖檔後,将圖檔以檔案的形式直接上傳到伺服器端,當上傳成功後,再将圖檔的路徑傳回到用戶端,插入到Summernote中即可!
最後,在Summernote組織的“問題正文”中,關于圖檔可能就隻是一段例如<img src="http://localhost:8080/1.jpg />這樣的代碼,就能夠減少資料庫的存儲資料量,同時,對于檔案的管理也會非常直覺。
47. 基于SpringMVC的檔案上傳
【本知識點的案例為:fileupload】
關于檔案上傳,在HTTP協定中規定:
必須使用POST方式送出請求;
在HTML表單中必須配置enctype="multipart/form-data";
另外,在HTML表單中必須使用<input type="file" />控件。
是以,可以将頁面設計為:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上傳圖檔</title>
</head>
<body>
<h1>上傳圖檔</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<p>請選擇您要上傳的檔案:<input type="file" name="image"></p>
<p><input type="submit" value="上傳"></p>
</form>
</body>
</html>
SpringMVC架構處理檔案上傳是基于commons-fileupload的,如果使用SpringMVC架構,需要自行添加這個依賴,如果使用SpringBoot架構則不需要,已經内置添加了。
在SpringMVC架構中,在控制器端會使用MultipartFile接口類型的參數來接收用戶端送出的上傳資料,在處理請求的方法中,直接聲明這個接口類型的參數即可,參數名應該與用戶端送出請求時的名稱保持一緻!在處理請求的過程中,調用MutlipartFile接口對象的void transferTo(File dest)方法就可以将圖檔保持到參數dest對應的檔案位置。
可以在伺服器端建立控制器處理上傳請求:
@RestController
public class FileUploadController {
@RequestMapping("/upload")
public String upload(MultipartFile image) throws IOException {
image.transferTo(new File("d:/1.jpg"));
return "OK";
}
}
注意:SpringBoot預設限制了上傳檔案的大小為1M / 10M(根據SpringBoot版本不同存在差異)。
關于檔案名的處理:
檔案名必須保證唯一,不要出現“覆寫上傳”的現象(即使你認為原有的檔案沒有用了,也不要覆寫);
擴充名應該與原始擴充名(檔案在用戶端裝置中的名稱)保持一緻,注意:如果某個檔案全名中隻有第1位是小數點,并沒有更多的小數點,是表示該檔案在Linux / MacOS中是隐藏檔案,小數點右側的并不是擴充名!
示例代碼:
@RequestMapping("/upload")
public String upload(MultipartFile image) throws IOException {
String parent = "d:/";
// 處理檔案名
// 關于檔案名的政策:時間 + 随機數
// 無論目前上傳功能是用于哪個用途,檔案名必須唯一
String filename = UUID.randomUUID().toString();
// 處理擴充名
// 擷取原始檔案名
String originalFilename = image.getOriginalFilename();
System.out.println("originalFilename=" + originalFilename);
// 暫定擴充名空字元串
String suffix = "";
// 如果原始檔案名中存在有效的擴充名,則截取
int beginIndex = originalFilename.lastIndexOf(".");
if (beginIndex > 0) {
suffix = originalFilename.substring(beginIndex);
}
// 得到完整的檔案名
String child = filename + suffix;
// 儲存上傳的檔案
image.transferTo(new File(parent, child));
return "OK";
}
後續,使用以上parent作為上傳的檔案夾即可。
在處理上傳時,關于MultipartFile的常用API有:
boolean isEmpty():判斷上傳的檔案是否為空,如果在表單中沒有選擇檔案,或選擇的檔案是0位元組的,即為空;
long getSize():擷取檔案大小,以位元組為機關;
String contentType:擷取文檔的MIME類型;
String getOriginalFilename():擷取上傳的檔案的原始檔案名;
void transferTo(File dest):儲存上傳的檔案。