这篇文章主要是记录一下在开发钉钉微应用时,实现图片上传及显示功能的过程。
这个项目用的dingyou-dingtalk-mobile这个脚手架,可直接在NowaGui上创建。这是一个关于钉钉微应用的脚手架,关于它的介绍以及更详细的内容,可以参考https://caohaijiang.github.io/2017/04/17/dingtalk-start/,对于刚入门使用react开发移动前端的同学还是很有帮助的。
该项目使用的前端UI是antd-mobile,其用户手册可以参看https://mobile.ant.design/docs/react/introduce-cn,里面提供了比较丰富的ui组件,基本上可以满足前端的开发。
转到重点,说一下其ImagePicker组件的实际应用。
前端的使用可以参考其用户手册,有比较详尽的实例说明,之前在开发时候也比较顺利的使用了这个组件,但是在将这个上传的图片,如何保存到后台服务器上,纠结了不少时间。网上看了不少相关文章,但是貌似都没什么帮助。
这边后端是通过springmvc来处理的,
@CrossOrigin( maxAge = 3600) @RequestMapping("/upload") @ResponseBody public String upload(HttpServletRequest request,@RequestParam("file") MultipartFile file) throws IOException
其中MultipartFIle file用来接收前端传过来的文件,前端应该如何传递过来,需要使用FormDate传递参数。如下
for(let key in this.state.files){ let formData = new FormData(); formData.append("file", this.state.files[key].file); formData.append("dateId", dateId); formData.append("flag", "1"); fetch(AUTH_URL + "ddoa/upload" , { method: 'POST', headers: { }, body: formData, }).then((response) => response.json()) .then((responseData)=> { console.log('uploadImage', responseData); Control.go("/leavedetail/"+dateId, ); }).catch((err)=> { this.showToast(); const msg = response.msg; Toast.info(msg, 2); }); }
如上,获取file将其设置到file中,在后台即可接收到。后端通过
FileUtils.copyInputStreamToFile(file.getInputStream(),new File(imagePath, imageName));
即可将文件上传到imagePath指定的目录中。完成图片的上传。此处需要将上传图片的相关的信息保存的至一张数据库表中,该表应该包括图片名称、图片实际路径、关联的主表Id等,根据业务进行拓展。
之后是将上传的图片在页面中显示了。
由于后端是springBoot项目,可以使用其提供的图片服务器来显示图片。可参考https://www.cnblogs.com/bestxyl/p/7403297.html来实现。
再需要后端写一个通过主键ID值获取相应图片名称的接口,搭配图片服务器即可显示出来了。
前端具体可如下实现
render() { const listForImage = (imagesList) => { let images = []; for(let i = 0; i < imagesList.length; i++) { let m = {url : AUTH_URL + 'images/' + imagesList[i].imageName,id : imagesList[i].id}; images.push( m ); } return images; } const files = listForImage(this.state.imagesList) ; return ( <div> <div style={{display: this.state.imagesList.length == 0 ? 'none' : ''}}> <WhiteSpace size="lg" /> <Card> <Card.Header title={<span><font color="gray"> * </font>图片</span>} /> <Card.Body style={{width : '90%'}}> <ImagePicker files={files} onImageClick={(index, fs) => console.log(index, fs)} selectable={false} multiple={false} /> </Card.Body> </Card> </div> </div> );
}
componentDidMount() { fetch( AUTH_URL + "ddoa/getImages" , { method: 'POST', headers: { }, body: formData, }).then((response) => { if (response.ok) { return response.json(); } }).then((json) => { const imagesList = json.images; this.setState({imagesList:imagesList}); }).catch((error) => { console.error(error); }); }