介紹:由於element的el-upload不支持文件夾上傳,所以用了vue-simple-uploader,實現了文件夾/文件的攜帶form data 和 headers參數上傳。vue-simple-uploader還能用於切分上傳、斷續上傳,此處項目沒有用到。
想對上傳做更多的處理的小夥伴,推薦去看源碼。
另:以下代碼加了文件列表的拖拽。
1、安裝:npm install vue-simple-uploader --save
2、
<uploader
ref="uploader"
:options="options"
:autoStart="false"
@file-added="onFileAdded"
@file-success="onFileSuccess"
@file-progress="onFileProgress"
@file-error="onFileError"
@class="uploader-app"
>
<uploader-unsupport></uploader-unsupport>
<uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">{{$t('imgUpload.file')}}</uploader-btn>
<uploader-btn :directory="true">{{$t('imgUpload.folder')}}</uploader-btn>
<uploader-list v-show="panelShow">
<div id="filePanel"
v-drag
draggable="false"
class="file-panel"
:class="{'mini': collapse}"
slot-scope="props"
>
<div class="file-title">
<h2>文件列表</h2>
<div class="operate">
<el-button @click="fileListShow" type="text">
<i :class="collapse ? 'el-icon-plus': 'el-icon-minus'"></i>
</el-button>
<el-button @click="close" type="text" title="關閉">
<i class="el-icon-close"></i>
</el-button>
</div>
</div>
<ul class="file-list">
<li v-for="file in props.fileList" :key="file.id">
<uploader-file :class="'file_' + file.id" ref="files" :file="file" :list="true"></uploader-file>
</li>
<div class="no-file" v-if="!props.fileList.length">
<i class="nucfont inuc-empty-file"></i> 暫無待上傳文件
</div>
</ul>
</div>
</uploader-list>
</uploader>
3、
options: {
target: process.env.API_ROOT + "/api/File/UploadByBuffer",//地址
testChunks: false, //不校驗
chunkSize: "10240000",
fileParameterName: "file", //上傳文件時文件的參數名,默認file
maxChunkRetries: 3, //最大自動失敗重試上傳次數
query:{
//form data裏的參數 根據實際需要
},
headers: {
// 在header中添加的驗證 根據實際需要
}
},
panelShow: false, //上傳列表的顯示
attrs: {
// 接受的文件類型 根據實際需要
accept: [".zip", ".rar"]
},
collapse: false ,//列表的縮放
curTop:undefined,//標記當前列表的位置
curLeft:undefined,//標記當前列表的位置
4、
//添加文件到列表 還未上傳
onFileAdded(file) {
this.panelShow = true;
//設置headers等參數的值
},
//上傳成功
onFileSuccess(rootFile, file, response, chunk) {
},
//文件進度的回調
onFileProgress(rootFile, file, chunk) {
},
//出錯
onFileError(rootFile, file, response, chunk) {
},
//上傳列表縮放
fileListShow() {
this.collapse = !this.collapse;
let oDiv = document.getElementById('filePanel')
if(this.collapse){
//屏幕高度
let h = document.body.clientHeight ||
window.innerHeight ||
document.documentElement.clientHeight ;
//屏幕寬度
let w = document.body.clientWidth ||
window.innerWidth ||
document.documentElement.clientWidth ;
this.curTop = oDiv.style.top;
this.curLeft = oDiv.style.left
oDiv.style.top = (h-40) + "px";
oDiv.style.left = (w-170) + "px";
}else{
//回到原來的位置
oDiv.style.top = this.curTop ;
oDiv.style.left = this.curLeft;
}
},
//關閉上傳列表
close() {
this.panelShow = false;
},
5、寫了拖拽(不是必要)
directives: {
drag(el) {
let oDiv = el; //當前元素
let self = this; //上下文
//禁止選擇網頁上的文字
document.onselectstart = function() {
return false;
};
oDiv.onmousedown = function(e) {
//鼠標按下,計算當前元素距離可視區的距離
let disX = e.clientX - oDiv.offsetLeft;
let disY = e.clientY - oDiv.offsetTop;
document.onmousemove = function(e) {
//通過事件委託,計算移動的距離
let l = e.clientX - disX;
let t = e.clientY - disY;
//屏幕高度
let h = document.body.clientHeight ||
window.innerHeight ||
document.documentElement.clientHeight ;
//屏幕寬度
let w = document.body.clientWidth ||
window.innerWidth ||
document.documentElement.clientWidth ;
//左邊菜單伸縮狀態的寬度 圖簡單直接寫了數字 嚴謹的小夥伴可以直接獲取側菜單的寬度
let leftBar = Cookies.get('sidebarStatus') == '0' ? 54 : 210
//判斷有沒有超過邊界點
if (l > (w - oDiv.offsetWidth)) l = w - oDiv.offsetWidth;
if(l < leftBar) l = leftBar;
if (t > (h - oDiv.offsetHeight)) t = h - oDiv.offsetHeight;
if (t < 50) t = 50;
//移動當前元素
oDiv.style.left = l + "px";
oDiv.style.top = t + "px";
};
document.onmouseup = function(e) {
document.onmousemove = null;
document.onmouseup = null;
};
//return false不加的話可能導致黏連,就是拖到一個地方時div粘在鼠標上不下來,相當於onmouseup失效
return false;
};
}
},
6、寫的樣式(當作參考拋磚引玉)
.uploader {
float: right;
.uploader-btn {
background: #f5921f;
color: #fff;
height: 30px;
font-weight: normal;
line-height: 24px;
border: 0px;
font-size: 12px;
}
.uploader-btn:hover {
background: #ebae67;
}
}
.file-panel {
position: fixed;
bottom: 10px;
right: 10px;
background: #fff;
box-shadow: 1px 1px 5px #ccc;
border-radius: 5px;
z-index: 2;
width: 650px;
height: 340px;
.file-title {
border: 1px solid #cccccc4a;
font-size: 10px;
height: 40px;
line-height: 40px;
padding-left: 10px;
h2 {
margin: 0px;
display: inline-block;
font-weight: normal;
color: #666363;
}
.operate {
float: right;
margin-right: 10px;
}
}
.file-list {
list-style-type: none;
height: 300px;
overflow-y: scroll;
padding: 0px;
margin: 0px;
width: 100%;
.uploader-file-info i {
display: none;
}
}
}
.mini {
right: -490px;
bottom: -306px;
.operate {
margin-right: 500px !important ;
}
}