小程序上传图片并回显
首先梳理一下便是:小程序类似于网页页面,因此上传回显其实和网页端的上传回显是类似的。
需求模拟
这边的一个需求便是:表单页面中包含一个上传图片的功能,并且上传后可以立即回显。
用到的框架有:uniapp、uview、springboot。
思路
整体的思路便是:使用 uview 框架自带的上传组件,并在 vue 页面中调用后端接口将图片上传至服务器即可。
关于回显,因为我还要做一个表单详情的页面,因此是通过获取服务器端已上传图片的url来进行回显的。
接下来,我们来查看代码。
代码
小程序端
上传组件相关的小程序端代码:
<u-upload customStyle="margin-left:25rpx"
:fileList="fileList1"
@afterRead="afterRead"
@delete="deletePic"
name="1"
multiple
:maxCount="1"
width="200"
height="200"
></u-upload>
此处是使用了 uview 自带的上传组件。详细内容请查看相关说明文档。
这里我们通过 multiple 和 :maxCount 对上传的图片个数做了限制,只能上传 1 张。
在 data 方法中定义图片列表 fileList1.
data(){
return{
fileList1:[]
}
}
在 methods 方法中定义上传组件的各种点击事件(删除、新增、上传)
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1)
},
// 新增图片
async afterRead(event) {
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}))
fileListLen++
}
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
console.log(this.fileList1[0].url);
let a = uni.uploadFile({
url: 'https://yourapi/upload/picture', // 仅为示例,非真实的接口地址
filePath: this.fileList1[0].url,
name: 'file',
formData: {
user: 'test'
},
success: (res) => {
getApp().globalData.imageUrl=res.data;
setTimeout(() => {
resolve(res.data.data)
}, 1000)
}
});
})
},
这里 uploadFilePromise
方法中的 getApp().globalData.imageUrl=res.data
;
是将调用上传接口返回的图片地址传给一个全局变量。
我们之后直接调用此全局变量进行图片回显就可以了。
提交按钮点击事件中的相关操作:
将图片地址传递给后端,存入数据库中,保证在别的页面通过api调用可以直接拿到图片的上传地址。
这里存入数据库的 url 均为存入服务器中的真实域名url,而非微信的 wxfile:// 或 http://tmp
submit() {
// 如果有错误,会在catch中返回报错信息数组,校验通过则在then中返回true
// this.uploadFile(0);
this.$refs.form1.validate().then(res => {
uni.$u.http.post('api/add', {
imageUrl: getApp().globalData.imageUrl,
}).then(res => {
uni.showToast({
icon: "success",
title: "提交成功"
});
});
})
}).catch(errors => {
uni.$u.toast(errors)
})
},
java后端
后端相关代码:
上传图片相关的控制层:
@RestController
@RequestMapping("/upload")
public class UploadController {
private static final Logger logger = LoggerFactory.getLogger(UploadController.class);
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
final String BaseUrl = "";//这里要拼接api的url
@Value("${file-save-path}")
private String fileSavePath;
@RequestMapping("/picture")
public String uploadPicture(HttpServletRequest request, HttpServletResponse response) throws Exception {
String filePath = "";
request.setCharacterEncoding("utf-8"); //设置编码
String directory =simpleDateFormat.format(new Date());
File dir = new File(fileSavePath+directory);
System.out.println(dir.getPath());
//创建一个名为当前年月日的文件夹,在文件夹中存放图片
if (!dir.isDirectory()) {
dir.mkdirs();
}
try {
StandardMultipartHttpServletRequest req = (StandardMultipartHttpServletRequest) request;
//获取formdata的值
Iterator<String> iterator = req.getFileNames();
while (iterator.hasNext()) {
MultipartFile file = req.getFile(iterator.next());
String fileName = file.getOriginalFilename();
//真正写到磁盘上
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String newFileName= UUID.randomUUID().toString().replaceAll("-", "")+suffix;
File file1 = new File(fileSavePath+directory+"/" + newFileName);
file.transferTo(file1);
System.out.println(file1.getPath());
//这里进行了路径拼接,根据自己的存放路径进行修改即可。
filePath = BaseUrl + "/uploads/images/" +directory+"/"+ newFileName;
}
} catch (Exception e) {
logger.error("", e);
}
return filePath;
}
}
文件路径配置
关于文件路径配置的问题。文件到底要怎么上传,要上传在哪里?这里给出配置代码。
思路
首先理清思路,
想要图片能够通过url能够直接访问到,那么我们:
第一步:要确保图片上传服务器指定位置成功。
首先要指定上传位置。
springboot 项目下的 resources 文件夹中的配置文件中加入以下配置:
可以不叫 file-save-path 和第三步 value 注解中的值对应上就好。
file-save-path: D:/images
第二步:域名是能打开的。(这里自己测试。)
第三步:域名拼接映射路径是可以成功映射的。
这里我们要自己编写一个 web 配置类。
我在这里做了关于 /images/的映射。这都是可以自行修改的。
改成别的的话,最后 图片的访问url就是 `https://url/yourmap/**`
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${file-save-path}")
private String fileSavePath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 配置资源映射
* 意思是:如果访问的资源路径是以“/images/”开头的,
* 就给我映射到本机的“E:/images/”这个文件夹内,去找你要的资源
* 注意:E:/images/ 后面的 “/”一定要带上
*/
// registry.addResourceHandler("/static/**")
// .addResourceLocations("file:"+fileSavePath);
// registry.addResourceHandler("/uploads/pic/**").addResourceLocations("file:"+fileSavePath);
registry.addResourceHandler("/images/**").addResourceLocations("file:"+fileSavePath);
}
}