基于Java后端图片上传代码编写以及前端uniapp图片上传页面编写(效果已实现)
springBoot图片上传代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.example.xunfei.controller; 2 3 4 import com.example.xunfei.config.uploadImgUtil; 5 import org.springframework.web.bind.annotation.CrossOrigin; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RestController; 8 import org.springframework.web.multipart.MultipartFile; 9 import org.springframework.web.multipart.MultipartHttpServletRequest; 10 11 import javax.servlet.http.HttpServletRequest; 12 13 @RestController 14 @RequestMapping("applet/customer/img") 15 @CrossOrigin 16 public class CustomerImgController { 17 18 19 private HttpServletRequest request; 20 21 @RequestMapping("upload") 22 public Object tt(HttpServletRequest request){ 23 MultipartHttpServletRequest req = (MultipartHttpServletRequest) request; 24 MultipartFile file = req.getFile("upload-images"); 25 if(file != null){ 26 String fName = uploadImgUtil.upload_Img(file); 27 return "http://8.140.176.58/img/"+fName; 28 }else{ 29 return "error"; 30 } 31 } 32 }
调用图片工具类,实现上传(自己编写)使用springframework.web.multipart中的MultipartFile
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.example.xunfei.config; 2 3 4 import org.springframework.web.multipart.MultipartFile; 5 6 import java.io.File; 7 import java.util.ArrayList; 8 import java.util.Calendar; 9 import java.util.List; 10 11 public class uploadImgUtil { 12 13 14 //商品图片上传多图片 15 16 17 private static String uploadFolder="c://images/"; 18 19 20 //商品图片 21 public static String upload_Img(MultipartFile file) { 22 23 if (file!=null){ 24 List<String> imageType =new ArrayList<>(); 25 imageType.add("jpg"); 26 imageType.add("png"); 27 imageType.add("jpeg"); 28 String itemHz= file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1).toLowerCase(); 29 System.out.println("----------------------"+file.getOriginalFilename()); 30 //开始操作上传 31 return getResponseData(file); 32 } 33 else return ""; 34 } 35 36 37 private static String getResponseData(MultipartFile file) { 38 String fName = ""; 39 if(file!=null){ 40 try { 41 String itemHz= file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1).toLowerCase(); 42 //获取文件名称 43 fName =getTime()+"."+itemHz; 44 45 String path = ""; 46 path= uploadFolder + "/" + fName; 47 file.transferTo(new File(path)); 48 } catch (Exception e) { 49 System.out.println(e.getMessage()); 50 51 } 52 } 53 return fName; 54 } 55 56 public synchronized static String getTime(){ 57 Calendar now = Calendar.getInstance(); 58 59 return now.get(Calendar.YEAR)+""+(now.get(Calendar.MONTH) + 1) + ""+now.get(Calendar.DAY_OF_MONTH)+""+ now.get(Calendar.HOUR_OF_DAY) 60 +""+now.get(Calendar.MINUTE)+""+now.get(Calendar.SECOND)+now.getTimeInMillis(); 61 62 } 63 64 65 }
uniapp前端代码如下:使用插件,支持App安卓打包,H5,微信小程序。其他需要测试。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <template> 2 <view style="background-color: #FFC878; width: 100%;"> 3 <view> 4 <view class="content-base-info1" style="padding-top: 30rpx;"> 5 <view class="conten-zhong1" > 6 <view style="margin-top: 12rpx; margin-left: 50upx; color: #585EB4; font-weight: 600; width: 100%;font-size: 34upx;"> 7 相册PHOTO</view> 8 <view style="margin-left: 40rpx;"> 9 <robby-image-upload style="float: left;" :value="imageData" :server-url="serverUrl" 10 :showUploadProgress="true" :limit="limitNumber" @delete="deleteImage" @add="addImage" 11 :enable-drag="enableDrag" :enable-del="enableDel" :enable-add="enableAdd"> 12 </robby-image-upload> 13 </view> 14 15 </view> 16 <!-- <view style="width: 98%;margin-left: 1%;"> 17 <button class="topbuts" @click="saveBut">保存</button> 18 </view> --> 19 </view> 20 </view> 21 </view> 22 </template> 23 24 <script> 25 import robbyImageUpload from '@/components/robby-image-upload/robby-image-upload.vue'; 26 export default { 27 28 data() { 29 return { 30 enableDel: true, 31 enableAdd: true, 32 enableDrag: true, 33 limitNumber: 1, 34 imageData: [], 35 serverUrl: 'http://8.140.176.58:8081/applet/customer/img/upload', 36 } 37 }, 38 components: { 39 robbyImageUpload, 40 }, 41 methods: { 42 //保存陪玩信息 43 saveBut() { 44 var _thst = this; 45 var strimg = _thst.imageData[0] 46 uni.request({ 47 method: 'POST', 48 data: { 49 "photoAlbum": strimg.toString(), 50 }, 51 dataType: 'json', 52 url: 'https://www.kk520.ltd/applet/customer/playWith/add', 53 success: (res) => { 54 console.log(res) 55 }, 56 }); 57 }, 58 deleteImage: function(e) { 59 console.log(e) 60 }, 61 addImage: function(e) { 62 this.imageData = e.allImages; 63 }, 64 } 65 } 66 </script> 67 68 <style> 69 .conten-zhong { 70 width: 98%; 71 height: 920upx; 72 background-color: #fff; 73 border-radius: 18upx; 74 margin-left: 1%; 75 margin-top: 20upx; 76 padding-top: 40upx; 77 } 78 .baseinfo-font { 79 width: 98%; 80 height: 80upx; 81 font-weight: 600; 82 background-color: #FFFFFF; 83 text-align: center; 84 margin-left: 1%; 85 line-height: 80upx; 86 font-weight: 600upx; 87 margin-top: 20upx; 88 border-radius: 20upx; 89 } 90 .content-base-info { 91 width: 98%; 92 margin-left: 1%; 93 height: 1000upx; 94 } 95 .topbuts { 96 width: 48%; 97 margin-top: 30upx; 98 float: right; 99 background-color: #fff; 100 color: #000; 101 } 102 .conten-zhong1 { 103 width: 98%; 104 height: 360upx; 105 background-color: #fff; 106 border-radius: 18upx; 107 margin-left: 1%; 108 margin-top: 20upx; 109 padding-top: 60upx; 110 } 111 .content-base-info1 { 112 width: 98%; 113 margin-left: 1%; 114 height: 1000upx; 115 } 116 </style>
图片上传插件(使用的uniapp插件库,感谢该插件作者)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <template> 2 <view class="imageUploadContainer"> 3 <view class="imageUploadList"> 4 <view class="imageItem" v-bind:key="index" v-for="(path,index) in imageListData"> 5 <image :src="path" :class="{'dragging':isDragging(index)}" draggable="true" @tap="previewImage" :data-index="index" @touchstart="start" @touchmove.stop.prevent="move" @touchend="stop"></image> 6 <view v-if="isShowDel" class="imageDel" @tap="deleteImage" :data-index="index">x</view> 7 </view> 8 <view v-if="isShowAdd" class="imageUpload" @tap="selectImage">+</view> 9 </view> 10 <image v-if="showMoveImage" class="moveImage" :style="{left:posMoveImageLeft, top:posMoveImageTop}" :src="moveImagePath"></image> 11 </view> 12 </template> 13 14 <script> 15 export default { 16 name:'robby-image-upload', 17 props: ['value','enableDel','enableAdd','enableDrag','serverUrl','formData','header', 'limit','fileKeyName','showUploadProgress','serverUrlDeleteImage'], 18 data() { 19 return { 20 imageBasePos:{ 21 x0: -1, 22 y0: -1, 23 w:-1, 24 h:-1, 25 }, 26 showMoveImage: false, 27 moveImagePath: '', 28 moveLeft: 0, 29 moveTop: 0, 30 deltaLeft: 0, 31 deltaTop: 0, 32 dragIndex: null, 33 targetImageIndex: null, 34 imageList: [], 35 isDestroyed: false 36 } 37 }, 38 mounted: function(){ 39 this.imageList = this.value 40 41 if(this.showUploadProgress === false){ 42 this.showUploadProgress = false 43 }else{ 44 this.showUploadProgress = true 45 } 46 }, 47 destroyed: function(){ 48 this.isDestroyed = true 49 }, 50 computed:{ 51 imageListData: function(){ 52 if(this.value){ 53 return this.value 54 } 55 }, 56 posMoveImageLeft: function(){ 57 return this.moveLeft + 'px' 58 }, 59 posMoveImageTop: function(){ 60 return this.moveTop + 'px' 61 }, 62 isShowDel: function(){ 63 if(this.enableDel === false){ 64 return false 65 }else{ 66 return true 67 } 68 }, 69 isShowAdd: function(){ 70 if(this.enableAdd === false){ 71 return false 72 } 73 74 if(this.limit && this.imageList.length >= this.limit){ 75 return false 76 } 77 78 return true 79 }, 80 isDragable: function(){ 81 if(this.enableDrag === false){ 82 return false 83 }else{ 84 return true 85 } 86 } 87 }, 88 methods:{ 89 selectImage: function(){ 90 var _self = this 91 if(!_self.imageList){ 92 _self.imageList = [] 93 } 94 95 uni.chooseImage({ 96 count: _self.limit ? (_self.limit - _self.imageList.length) : 999, 97 success: function(e){ 98 var imagePathArr = e.tempFilePaths 99 100 //如果设置了limit限制,在web上count参数无效,这里做判断控制选择的数量是否合要求 101 //在非微信小程序里,虽然可以选多张,但选择的结果会被截掉 102 //在app里,会自动做选择数量的限制 103 if(_self.limit){ 104 var availableImageNumber = _self.limit - _self.imageList.length 105 if(availableImageNumber < imagePathArr.length){ 106 uni.showToast({ 107 title: '图片总数限制为'+_self.limit+'张,当前还可以选'+availableImageNumber+'张', 108 icon:'none', 109 mask: false, 110 duration: 2000 111 }); 112 return 113 } 114 } 115 116 //检查服务器地址是否设置,设置即表示图片要上传到服务器 117 if(_self.serverUrl){ 118 uni.showToast({ 119 title: '上传进度:0/' + imagePathArr.length, 120 icon: 'none', 121 mask: false 122 }); 123 124 var remoteIndexStart = _self.imageList.length - imagePathArr.length 125 var promiseWorkList = [] 126 var keyname = (_self.fileKeyName ? _self.fileKeyName : 'upload-images') 127 var completeImages = 0 128 129 for(let i=0; i<imagePathArr.length;i++){ 130 promiseWorkList.push(new Promise((resolve, reject)=>{ 131 let remoteUrlIndex = remoteIndexStart + i 132 uni.uploadFile({ 133 url:_self.serverUrl, 134 fileType: 'image', 135 header: _self.header, 136 formData:_self.formData, 137 filePath: imagePathArr[i], 138 name: keyname, 139 success: function(res){ 140 if(res.statusCode === 200){ 141 if(_self.isDestroyed){ 142 return 143 } 144 145 completeImages ++ 146 147 if(_self.showUploadProgress){ 148 uni.showToast({ 149 title: '上传进度:' + completeImages + '/' + imagePathArr.length, 150 icon: 'none', 151 mask: false, 152 duration: 500 153 }); 154 } 155 console.log('success to upload image: ' + res.data) 156 resolve(res.data) 157 }else{ 158 console.log('fail to upload image:'+res.data) 159 reject('fail to upload image:' + remoteUrlIndex) 160 } 161 }, 162 fail: function(res){ 163 console.log('fail to upload image:'+res) 164 reject('fail to upload image:' + remoteUrlIndex) 165 } 166 }) 167 })) 168 } 169 Promise.all(promiseWorkList).then((result)=>{ 170 if(_self.isDestroyed){ 171 return 172 } 173 174 for(let i=0; i<result.length;i++){ 175 _self.imageList.push(result[i]) 176 } 177 178 _self.$emit('add', { 179 currentImages: imagePathArr, 180 allImages: _self.imageList 181 }) 182 _self.$emit('input', _self.imageList) 183 }) 184 }else{ 185 for(let i=0; i<imagePathArr.length;i++){ 186 _self.imageList.push(imagePathArr[i]) 187 } 188 189 _self.$emit('add', { 190 currentImages: imagePathArr, 191 allImages: _self.imageList 192 }) 193 _self.$emit('input', _self.imageList) 194 } 195 } 196 }) 197 }, 198 deleteImage: function(e){ 199 var imageIndex = e.currentTarget.dataset.index 200 var deletedImagePath = this.imageList[imageIndex] 201 this.imageList.splice(imageIndex, 1) 202 203 //检查删除图片的服务器地址是否设置,如果设置则调用API,在服务器端删除该图片 204 if(this.serverUrlDeleteImage){ 205 uni.request({ 206 url: this.serverUrlDeleteImage, 207 method: 'GET', 208 data: { 209 imagePath: deletedImagePath 210 }, 211 success: res => { 212 console.log(res.data) 213 } 214 }); 215 } 216 217 this.$emit('delete',{ 218 currentImage: deletedImagePath, 219 allImages: this.imageList 220 }) 221 this.$emit('input', this.imageList) 222 }, 223 previewImage: function(e){ 224 var imageIndex = e.currentTarget.dataset.index 225 uni.previewImage({ 226 current: this.imageList[imageIndex], 227 indicator: "number", 228 loop: "true", 229 urls:this.imageList 230 }) 231 }, 232 initImageBasePos: function(){ 233 let paddingRate = 0.024 234 var _self = this 235 //计算图片基准位置 236 uni.getSystemInfo({ 237 success: function(obj) { 238 let screenWidth = obj.screenWidth 239 let leftPadding = Math.ceil(paddingRate * screenWidth) 240 let imageWidth = Math.ceil((screenWidth - 2*leftPadding)/4) 241 242 _self.imageBasePos.x0 = leftPadding 243 _self.imageBasePos.w = imageWidth 244 _self.imageBasePos.h = imageWidth 245 } 246 }) 247 }, 248 findOverlapImage: function(posX, posY){ 249 let rows = Math.floor((posX-this.imageBasePos.x0)/this.imageBasePos.w) 250 let cols = Math.floor((posY-this.imageBasePos.y0)/this.imageBasePos.h) 251 let indx = cols*4 + rows 252 return indx 253 }, 254 isDragging: function(indx){ 255 return this.dragIndex === indx 256 }, 257 start: function(e){ 258 console.log(this.isDragable) 259 if(!this.isDragable){ 260 return 261 } 262 this.dragIndex = e.currentTarget.dataset.index 263 this.moveImagePath = this.imageList[this.dragIndex] 264 this.showMoveImage = true 265 266 //计算纵向图片基准位置 267 if(this.imageBasePos.y0 === -1){ 268 this.initImageBasePos() 269 270 let basePosY = Math.floor(this.dragIndex / 4) * this.imageBasePos.h 271 let currentImageOffsetTop = e.currentTarget.offsetTop 272 this.imageBasePos.y0 = currentImageOffsetTop - basePosY 273 } 274 275 //设置选中图片当前左上角的坐标 276 this.moveLeft = e.target.offsetLeft 277 this.moveTop = e.target.offsetTop 278 }, 279 move: function(e){ 280 if(!this.isDragable){ 281 return 282 } 283 const touch = e.touches[0] 284 this.targetImageIndex = this.findOverlapImage(touch.clientX, touch.clientY) 285 286 //初始化deltaLeft/deltaTop 287 if(this.deltaLeft === 0){ 288 this.deltaLeft = touch.clientX - this.moveLeft 289 this.deltaTop = touch.clientY - this.moveTop 290 } 291 292 //设置移动图片位置 293 this.moveLeft = touch.clientX - this.deltaLeft 294 this.moveTop = touch.clientY - this.deltaTop 295 }, 296 stop: function(e){ 297 if(!this.isDragable){ 298 return 299 } 300 if(this.dragIndex !== null && this.targetImageIndex !== null){ 301 if(this.targetImageIndex<0){ 302 this.targetImageIndex = 0 303 } 304 305 if(this.targetImageIndex>=this.imageList.length){ 306 this.targetImageIndex = this.imageList.length-1 307 } 308 //交换图片 309 if(this.dragIndex !== this.targetImageIndex){ 310 this.imageList[this.dragIndex] = this.imageList[this.targetImageIndex] 311 this.imageList[this.targetImageIndex] = this.moveImagePath 312 } 313 } 314 315 this.dragIndex = null 316 this.targetImageIndex = null 317 this.deltaLeft = 0 318 this.deltaTop = 0 319 this.showMoveImage = false 320 321 this.$emit('input', this.imageList) 322 } 323 } 324 } 325 </script> 326 327 <style> 328 .imageUploadContainer{ 329 padding: 10upx 5upx; 330 margin: 10upx 5upx; 331 } 332 333 .dragging{ 334 transform: scale(1.2) 335 } 336 337 .imageUploadList{ 338 display: flex; 339 flex-wrap: wrap; 340 } 341 342 .imageItem, .imageUpload{ 343 width: 160upx; 344 height: 160upx; 345 margin: 10upx; 346 } 347 348 .imageDel{ 349 position: relative; 350 left: 120upx; 351 bottom: 165upx; 352 background-color: rgba(0,0,0,0.5); 353 width: 36upx; 354 text-align: center; 355 line-height: 35upx; 356 border-radius: 17upx; 357 color: white; 358 font-size: 30upx; 359 padding-bottom: 2upx; 360 } 361 362 .imageItem image, .moveImage{ 363 width: 160upx; 364 height: 160upx; 365 border-radius: 8upx; 366 } 367 368 .imageUpload{ 369 line-height: 130upx; 370 text-align: center; 371 font-size: 150upx; 372 color: #D9D9D9; 373 border: 1px solid #D9D9D9; 374 border-radius: 8upx; 375 } 376 377 .moveImage{ 378 position: absolute; 379 } 380 </style>
实现效果,如图:
上传成功如图: