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      100px;
198     text-align: center;
199   }
200 
201   .vue-uploader .file-list .file-item img {
202      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      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      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>
原文地址:https://www.cnblogs.com/ronle/p/10868196.html