分享一份django+vue+element的上传文件进度的简易实现。
采用的是半分离,没有用到vue-cli
需求是上传csv文件,但模板的内容比较小,为了实现一下进度条的效果,暂时没有做文件格式的限制
效果
1 前端核心代码
-
html
<div class="form-group" v-for="(l, index) in data.regions"> <label class="col-sm-2 control-label">地区名称</label> <div class="col-sm-4"> ..... </div> <div class="col-sm-4"> <div class="col-sm-6"> <button class="btn btn-xs btn-warning" v-show="!l.file.name">请选择csv文件</button> <el-progress :text-inside="true" :stroke-width="24" :percentage="l.file.process" :status="l.file.status" v-show="l.file.name"></el-progress> </div> <div class="col-sm-6"> <button class="btn btn-xs btn-success" type="button" @click="selectFile($event)">上传文件</button> <input type="file" v-show="false" @change="upload($event, index)"> </div> </div> <div class="col-sm-2"> <button class="btn btn-xs btn-danger" type="button" @click="del(index)" v-show="index!==0">-</button> <button class="btn btn-xs btn-primary" type="button" @click="add" v-show="index===data.regions.length-1">+</button> </div> </div>
-
js
let vm1 = new Vue({ el: '#myModal1', delimiters: ['[[', ']]'], data: { name: '', witch: '', data: { name: '', logic_env: '', battle_env: '', regions: [ { region_id: '', file: { name: '', remote_src: '', status: null, process: 0 } }, ], }, }, methods: { selectFile(event) { let file = event.target.nextElementSibling file.click() }, upload(event, index) { let file = event.target.files[0] let which = this.data.regions[index] if (!file) { toastr.warning('请选择文件') return } which.file.name = file.name let formData = new FormData(); let that = this formData.append('file', file) which.file.status = null axios({ method: 'post', url: '/swan/uploads/', // headers: {'Content-Type': 'multipart/form-data'}, data: formData, onUploadProgress(progressEvent) { if (progressEvent.lengthComputable) { let val = (progressEvent.loaded / progressEvent.total * 100).toFixed(0); console.log(parseInt(val)) which.file.process = parseInt(val) } } }).then(response => { console.log(response.data.data.remote_src) which.file.status = 'success' }) .catch(error => { which.file.status = 'exception'; // 进度为0看不到颜色,不好判断,所以设置了30 which.file.process = 30; toastr.error(error.response.data.msg) }) }, add() { this.data.regions.push({ region_id: '', file: { name: '', remote_src: '', status: null, process: 0 } }) }, del(index) { this.data.regions.splice(index, 1) }, submit: function () { let url = this.submitUrl; let data = this.data; axios.post(url, data) .then(function (response) { toastr.success(response.data.msg); vm.search(); vm.$refs.refLogic.getoption() vm.$refs.refBattle.getoption() vm.$refs.refRegion.getoption() }) .catch(function (err) { toastr.error(err.response.data.msg) }); $('#myModal1').modal('hide') } } })
2 后端
def upload(request):
"""上传文件"""
BASE_DIR = '/tmp/test/'
if request.method == 'POST':
file = request.FILES.get('file', None)
if file is None:
raise KeyError('请选择上传文件')
os.popen('mkdir -p {base}'.format(base=BASE_DIR))
file_dir = os.path.join(BASE_DIR, file.name)
with open(file_dir, 'wb') as f:
for chunk in file.chunks():
f.write(chunk)
return response_200_success(data={'remote_src': file_dir})