實作 Vue 拖拉檔案上傳並透過 Java 後端處理
2019-02-26
/
簡單實作 Vue 的拖拉檔案上傳並透過 Ajax 呼叫 Java 後端 API 來處理上傳的檔案內容,後端的部份因為 Server 問題,僅留後端程式碼、注意事項和截圖結果呈現。
Demo 以及 CodePen 部分皆只呈現前端頁面的部份並使用 CDN
的方式引入,而 CodePen 有使用 Bootstrap 的按鈕, 上傳 icon 則是 FontAwesome,有需要請自行引入!
以下為前端頁面拖拉檔案或點擊上傳的部份,上傳後可以分析出檔案的一些資訊,上傳完後也會出現刪除檔案的按鈕。而範例的 code 會加上呼叫後端 API 的段落並利用 axios
來呼叫。
前端 Demo(不包含呼叫後端 api 但範例 code 會貼上):
Drop file or click to upload
extension support: txt
maximum file size: 5 MB
fileName:
fileZise(bytes):
extension:
前往 CodePen 觀看
CSS:
.dropZone {
height: 200px;
position: relative;
border: 2px dashed #eee;
}
.dropZone:hover {
border: 2px solid #2e94c4;
}
.dropZone:hover .dropZone-title {
color: #1975A0;
}
.dropZone-info {
color: #A8A8A8;
position: absolute;
top: 50%;
width: 100%;
transform: translate(0, -50%);
text-align: center;
}
.dropZone-title {
color: #787878;
}
.dropZone input {
position: absolute;
cursor: pointer;
top: 0px;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.dropZone-upload-limit-info {
display: flex;
justify-content: flex-start;
flex-direction: column;
}
.dropZone-over {
background: #5C5C5C !important;
opacity: 0.8;
border: 2px solid #2e94c4;
}
.dropZone-uploaded {
height: 200px;
position: relative;
border: 2px dashed #eee;
}
.dropZone-uploaded-info {
display: flex;
flex-direction: column;
align-items: center;
color: #A8A8A8;
position: absolute;
top: 50%;
width: 100%;
transform: translate(0, -50%);
text-align: center;
}
.removeFile {
width: 200px;
}
.btn-primary {
color: #fff;
background-color: #1170C8;
border-radius: 5px;
}
HTML:
<div id="app">
<div v-if="!file">
<div :class="['dropZone', dragging ? 'dropZone-over' : '']" @dragestart="dragging = true" @dragenter="dragging = true" @dragleave="dragging = false">
<div class="dropZone-info" @drag="onChange">
<!-- font-awesome upload icon -->
<span class="fa fa-cloud-upload dropZone-title"></span>
<span class="dropZone-title">Drop file or click to upload</span>
<div class="dropZone-upload-limit-info">
<div>extension support: txt</div>
<div>maximum file size: 5 MB</div>
</div>
</div>
<input type="file" @change="onChange">
</div>
</div>
<div v-else class="dropZone-uploaded">
<div class="dropZone-uploaded-info">
<span class="dropZone-title">Uploaded</span>
<button type="button" class="btn btn-primary removeFile" @click="removeFile">Remove File</button>
</div>
</div>
<div class="uploadedFile-info">
<div>fileName: {{ file.name }}</div>
<div>fileZise(bytes): {{ file.size }}</div>
<div>extension:{{ extension }}</div>
</div>
</div>
JavaScript:
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
var app = new Vue({
el: 'app',
data() {
return {
file: '',
dragging: false
}
},
methods: {
onChange(e) {
// 判斷拖拉上傳或點擊上傳的 event
var files = e.target.files || e.dataTransfer.files;
// 預防檔案為空檔
if (!files.length) {
this.dragging = false;
return;
}
this.createFile(files[0]);
},
createFile(file) {
// 附檔名判斷
if (!file.type.match('text.*')) {
alert('please select txt file');
this.dragging = false;
return;
}
// 檔案大小判斷
if (file.size > 5000000) {
alert('please check file size no more than 5 MB')
this.dragging = false;
return;
}
this.file = file;
this.dragging = false;
// axios post 的 url 記得更換你自己的 api url
let json = new FormData();
json.append('uploadFile', this.file)
axios.post('http://localhost:8080/uploadFile', json
{
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(res => {
if (res.data !== null && res.data.length > 1) {
console.log(res.data)
}
})
},
removeFile() {
this.file = '';
}
},
computed: {
// 前端擷取附檔名
extension() {
return (this.file) ? this.file.name.split('.').pop() : '';
}
}
});
後端 Java 部分(以 SrpingMVC 為例子):
configuration multipartResolver(我的環境是在 applicationContext-webapp.xml 底下):
如果沒有設定會噴 error log
!
<!-- for <form ... enctype="multipart/form-data" /> -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- The maximum file size in bytes -->
<property name="maxUploadSize" value="5000000" />
</bean>
controller:
...
// your file process service
@Autowired FileSerivce fileService;
...
@PostMapping("uploadFile")
@ResponseBody
public String searchSimilarDocumentByDocument(@RequestParam("uploadFile") MultipartFile file) {
return new fileService.txtToString(file);
}
...
service:
...
// 不過這個做成 utils 可能比較適合
public static String txtToString(MultipartFile file) throws IOException {
return new String(file.getBytes(), "UTF-8").trim();
}
...
Test Result:
input: test.txt
context: 測試文件

log result:

Note:
code 都是簡單的範例應用,礙於 server 緣故,後端的實作基本上就是貼重要的 code 和擷取結果,之後前端利用 axios
接收到剛剛的結果在看要怎麼去處理像是輸出的某些地方之類的。而真實使用的時候一些例外處理還有副檔名前後端處理,最後前端要取的什麼訊息或錯誤訊息都得記得補上哦。