vue的formdata图片预览以及上传
1 <template> 2 <div class="vue-uploader"> 3 <div class="file-list"> 4 <section v-for="(file, index) of files" class="file-item draggable-item"> 5 <img :src="file.src" alt="" ondragstart="return false;"> 6 <p class="file-name">{{file.name}}</p> 7 <span class="file-remove" @click="remove(index)">+</span> 8 </section> 9 <section v-if="status === 'ready'" class="file-item"> 10 <div @click="add" class="add"> 11 <span>+</span> 12 </div> 13 </section> 14 </div> 15 16 <section v-if="files.length !== 0" class="upload-func"> 17 <div class="progress-bar"> 18 <section v-if="uploading" :width="(percent * 100) + '%'">{{(percent * 100) + '%'}}</section> 19 </div> 20 <div class="operation-box"> 21 <button v-if="status === 'ready'" @click="submit">上传</button> 22 <button v-if="status === 'finished'" @click="finished">完成</button> 23 </div> 24 </section> 25 <input type="file" accept="image/*" @change="fileChanged" ref="file" multiple="multiple"> 26 27 <el-upload 28 action="https://jsonplaceholder.typicode.com/posts/" 29 list-type="picture-card" 30 :auto-upload="false" 31 :limit="9" 32 :on-preview="handlePictureCardPreview" 33 :on-remove="handleRemove" 34 :http-request="uploadFile" 35 ref="upload" 36 accept="image/png,image/gif,image/jpg,image/jpeg" 37 > 38 <i class="el-icon-plus"></i> 39 </el-upload> 40 <el-dialog :visible.sync="dialogVisible"> 41 <img width="100%" :src="dialogImageUrl" alt=""> 42 </el-dialog> 43 <el-button type="primary" @click="subPicForm">上传</el-button> 44 </div> 45 </template> 46 47 <script> 48 import axios from "axios" 49 50 export default { 51 // props: { 52 // src: { 53 // type: String, 54 // required: true 55 // } 56 // }, 57 data() { 58 return { 59 status: 'ready', 60 files: [], 61 point: {}, 62 uploading: false, 63 percent: 0, 64 dialogImageUrl: '', 65 dialogVisible: false, 66 formDate: "" 67 } 68 }, 69 methods: { 70 add() { 71 this.$refs.file.click() 72 }, 73 submit() { 74 if (this.files.length === 0) { 75 console.warn('no file!'); 76 return 77 } 78 const formData = new FormData(); 79 this.files.forEach((item) => { 80 formData.append(item.name, item.file) 81 }); 82 const xhr = new XMLHttpRequest(); 83 xhr.upload.addEventListener('progress', this.uploadProgress, false); 84 xhr.open('POST', "/api/upload", this.src, true); 85 this.uploading = true; 86 xhr.send(formData); 87 xhr.onload = () => { 88 this.uploading = false; 89 if (xhr.status === 200 || xhr.status === 304) { 90 this.status = 'finished'; 91 console.log('upload success!') 92 } else { 93 console.log(`error:error code ${xhr.status}`) 94 } 95 } 96 }, 97 finished() { 98 this.files = []; 99 this.status = 'ready' 100 }, 101 remove(index) { 102 this.files.splice(index, 1) 103 }, 104 fileChanged() { 105 const list = this.$refs.file.files; 106 for (let i = 0; i < list.length; i++) { 107 if (!this.isContain(list[i])) { 108 const item = { 109 name: list[i].name, 110 size: list[i].size, 111 file: list[i] 112 }; 113 this.html5Reader(list[i], item); 114 this.files.push(item) 115 } 116 } 117 this.$refs.file.value = '' 118 }, 119 // 将图片文件转成BASE64格式 120 html5Reader(file, item) { 121 const reader = new FileReader(); 122 reader.onload = (e) => { 123 this.$set(item, 'src', e.target.result) 124 }; 125 reader.readAsDataURL(file) 126 }, 127 isContain(file) { 128 this.files.forEach((item) => { 129 if (item.name === file.name && item.size === file.size) { 130 return true 131 } 132 }); 133 return false 134 }, 135 // 上传进度 136 uploadProgress(evt) { 137 const component = this; 138 if (evt.lengthComputable) { 139 const percentComplete = Math.round((evt.loaded * 100) / evt.total); 140 component.percent = percentComplete / 100 141 } else { 142 console.warn('upload progress unable to compute') 143 } 144 }, 145 // elementUI上传 146 uploadFile(file) { 147 this.formDate.append('file', file.file); 148 }, 149 handlePictureCardPreview(file) { 150 this.dialogImageUrl = file.url; 151 this.dialogVisible = true; 152 }, 153 handleRemove(file, fileList) { 154 console.log(file, fileList); 155 }, 156 subPicForm() { 157 this.formDate = new FormData(); 158 this.$refs.upload.submit(); 159 this.formDate.append('WS_CODE', "12133"); 160 let config = { 161 headers: { 162 'Content-Type': 'multipart/form-data' 163 } 164 }; 165 axios.post("/api/upload", this.formDate, config).then(res => { 166 console.log(res) 167 }).catch(res => { 168 console.log(res) 169 }) 170 } 171 } 172 } 173 </script> 174 175 <style scoped> 176 .vue-uploader { 177 border: 1px solid #e5e5e5; 178 } 179 180 .vue-uploader .file-list { 181 padding: 10px 0px; 182 } 183 184 .vue-uploader .file-list:after { 185 content: ''; 186 display: block; 187 clear: both; 188 visibility: hidden; 189 line-height: 0; 190 height: 0; 191 font-size: 0; 192 } 193 194 .vue-uploader .file-list .file-item { 195 float: left; 196 position: relative; 197 width: 100px; 198 text-align: center; 199 } 200 201 .vue-uploader .file-list .file-item img { 202 width: 80px; 203 height: 80px; 204 border: 1px solid #ececec; 205 } 206 207 .vue-uploader .file-list .file-item .file-remove { 208 position: absolute; 209 right: 12px; 210 display: none; 211 top: 4px; 212 width: 14px; 213 height: 14px; 214 color: white; 215 cursor: pointer; 216 line-height: 12px; 217 border-radius: 100%; 218 transform: rotate(45deg); 219 background: rgba(0, 0, 0, 0.5); 220 } 221 222 .vue-uploader .file-list .file-item:hover .file-remove { 223 display: inline; 224 } 225 226 .vue-uploader .file-list .file-item .file-name { 227 margin: 0; 228 height: 40px; 229 word-break: break-all; 230 font-size: 14px; 231 overflow: hidden; 232 text-overflow: ellipsis; 233 display: -webkit-box; 234 -webkit-line-clamp: 2; 235 -webkit-box-orient: vertical; 236 } 237 238 .vue-uploader .add { 239 width: 80px; 240 height: 80px; 241 margin-left: 10px; 242 float: left; 243 text-align: center; 244 line-height: 80px; 245 border: 1px dashed #ececec; 246 font-size: 30px; 247 cursor: pointer; 248 } 249 250 .vue-uploader .upload-func { 251 display: flex; 252 padding: 10px; 253 margin: 0px; 254 background: #f8f8f8; 255 border-top: 1px solid #ececec; 256 } 257 258 .vue-uploader .upload-func .progress-bar { 259 flex-grow: 1; 260 } 261 262 .vue-uploader .upload-func .progress-bar section { 263 margin-top: 5px; 264 background: #00b4aa; 265 border-radius: 3px; 266 text-align: center; 267 color: #fff; 268 font-size: 12px; 269 transition: all .5s ease; 270 } 271 272 .vue-uploader .upload-func .operation-box { 273 flex-grow: 0; 274 padding-left: 10px; 275 } 276 277 .vue-uploader .upload-func .operation-box button { 278 padding: 4px 12px; 279 color: #fff; 280 background: #007ACC; 281 border: none; 282 border-radius: 2px; 283 cursor: pointer; 284 } 285 286 .vue-uploader > input[type="file"] { 287 display: none; 288 } 289 </style>