简单阐述一下存与取两者之中的一些雷。(主要用Mybatis哈)
存放过程:①列的类型设置为"bytea",在JAVA中用byte[]读取。
②注意SQL语句与常用MYSQL、msSQL之间的差别。(如莫名其妙的单双引号)
③存放过程中,切记要用“#{}”来作bytea的占位符,而不是用“${}”。(使用#{}是好习惯,可以防止SQL注入攻击。在别的数据库可能体现不出来两者差别,但PostgreSQL很多参数都要用单引号''来标出来,否则执行SQL语句会报错,于是乎存在 '${}' 和 #{} 两种传参方式,生动地说明了什么是直接替换和预编辑。)
在下面两个语句中,如果使用了上者,那么恭喜你,图片大概率完整的存储到数据库中了,但下者则没那么好运了,因为直接替换型传参可能会造成大量字节的丢失,图片直接被破坏了。
@Insert("INSERT INTO public.\"Image\" (data) VALUES( #{data} )")
@Insert("INSERT INTO public.\"Image\" (data) VALUES( ${data} )")
④Java中对应的数据类型为byte[],建议使用MultipartFile file来作上传函数的参数,用file.getBytes()把文件(图片,二进制方式存储的)转换为byte数组。上传图片方式多种多样,我就不赘述了。
总结:注意语句的设计、注意传参的使用、注意类型的设置。
存入后,可以导出数据库中表的内容,来判断有无存储成功。
取出过程:主要讲如何将表中的图片投映到网页中吧。
①使用注解执行SQL时,注意设计合适的实体类和Mapper接口返回的类型。
譬如下面的代码,Image表中的各列我都在实体类中Image中定义了,所以Service调用后搜索结果会自动一一映射到我们实体类Image的(临时)变量中,非常的方便,Controller中可以直接获得。(代码并不完整,只是举例说明实体类和返回类型的设计的便利)
@Select("SELECT * FROM public.\"Image\" ORDER BY upload_date DESC")
Image[] GetImage();
@GetMapping("/image-get")
public List<String> getImage() throws IOException {
Image[] images = imageService.GetImage();
②使用byte[]型读取到后端,并且在后端将之转为String型的Base64图片。
上述代码之所是String列表而不是byte[]列表,就说明要在后端将数据加工后再传给前端。原因很简单,前端解码效率低,Base64这种好处理太多了。
for (Image image : images) {
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(image.getData()));
String base64Image = imageToBase64(bufferedImage);
base64Images.add(base64Image);
}
中间转为BufferedImage,是可以帮助我们事先检查一下提取出来的图片是否可以正常显示。返回前端的是base64Images。
③前端处理。
这部分花样很多,这里给个例子:简单理解就是创建一个图片数组images,在钩子函数中创立一个image实体,包含图像数据本身和新增的URL(因为html中常用img src来载入图片)。使用fetch调用GetMapping,此时会获得一个保留图片数组数据的json文件,遍历它,将每张图片塞入images数组中,并设置每张图片对应的src值。
new Vue({
el: '#image',
data() {
return {
images: []
};
},
mounted() {
console.log('mounted 钩子函数被调用,实例已挂载到 DOM');
fetch('/image-get')
.then(response => response.json())
.then(base64Images => {
for (const base64Image of base64Images) {
const img = new Image();
img.onload = () => {
this.images.push(img);
};
img.src = 'data:image/jpeg;base64,' + base64Image;
}
})
.catch(error => {
this.$message.error('图片传输失败');
});
}
})
;
那么html就好写了:
<div v-for="image in images" class="image-item">
<img :src="image.src" >
</div>
之后打开对应网页,不出意外数据库中的图片应该能显现出来了。