摸索了一个多星期,终于解决了展示瀑布流照片墙的问题,我一直在思考照片放在哪里,前后想了很多方案。最开始是想把照片放在本地(我的E盘中),而数据库中只存照片的名字,但是这种方案遇到了瓶颈,我不知道img标签的src路径怎么写,不能直接写我本地的路径,在网上看了很多,说是要把图片放到服务器下。但是这样我又遇到了一个问题(问题真是频繁啊),因为我创建的是maven工程,之前把maven工程部署到自己配置的tomcat服务器上的时候各种错误,并且也没解决这个问题,我只好将maven工程部署到了STS自带的tomcat服务器上,那现在要把图片放在服务器的目录下,就需要找到tomcat的webapp目录,自己配置的服务器的话这个目录很好找,但是STS自带的tomcat服务器这个目录我又不知道在哪里,所以这种方案又放弃了。既然我找不到这个目录,网上又说可以把自己的某个文件夹当做服务器下的文件夹,所以把我想修改tomcat的server.xml文件,同样是由于找不到STS自带的tomcat服务器下的这个目录,所以这种方案我研究了很久还是不行。后来我又想着还是把图片转换成二进制流存到数据库里面吧,然后再从数据库中读出来,之前我一直想着把图片信息转换成json字符串传递到前台,传递到前台这个过程我是做到了,但是如何在前台将图片的二进制信息转换成图片显示呢,这个过程我又纠结了很久,我一直在想着在js中如何将图片的二进制流转换成图片显示,但是在网上找了很久之后,大家有的说js不能处理二进制流,这种办法也不适用。
后来是通过把图片二进制信息写入到HttpServletResponse 的outputStream输出流中来展示的,最开始我只是在SpringMVC的一个controller中来处理这个过程,将这一个controller中同时处理,然后返回jsp页面,发现根本不行啊,下面是我当时错误的代码形式:
[java] view plain copy print?
@RequestMapping(value="/toLookImage",method = RequestMethod.GET)
public String lookImage(@PathParam("id")int id,HttpServletRequest request,HttpServletResponse response,Model model){
HttpSession seesion = request.getSession();
Photo photo=photoService.getPhotoById(new BigDecimal(id));
byte[] data=photo.getPhotoData();
response.setContentType("img/jpeg");
response.setCharacterEncoding("utf-8");
try {
OutputStream outputStream=response.getOutputStream();
InputStream in=new ByteArrayInputStream(data);
int len=0;
byte[]buf=new byte[1024];
while((len=in.read(buf,0,1024))!=-1){
outputStream.write(buf, 0, len);
}
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "test";
}
其中test.jsp便是我要显示图片的页面,原来我犯了很蠢的错误,应该让一个Controller来返回页面,另一个Controller来显示图片。终于这样我实现了从数据库中读取图片然后显示到页面上。下面来展示下我正确的代码流程:
(1)首先将图片上传然后存到数据库中,代码如下:
[java] view plain copy print?
@Controller
@Configuration
@ImportResource("classpath:spring.xml")
@RequestMapping("/photo")
public class FileUploadController {
@Resource
private IPhotoService photoService;
@RequestMapping(value="/tofile")
public String toFileUpLoad(HttpServletRequest request,Model model){
return "fileUpLoad";
}
//@Value("#{settings['picPath.picUrl']}")
@Value("${picUrl}")
private String picUrl;
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
@RequestMapping("/addAction.do")
@ResponseBody//将返回结果写到response中
public String save(HttpServletRequest request,HttpServletResponse response,Model model,@RequestParam(value="photo",required=false)MultipartFile filedata) throws UnsupportedEncodingException{
if(filedata!=null&&!filedata.isEmpty()){
//获取图片的文件名
String fileName=filedata.getOriginalFilename();
//获取图片的扩展名
String extensionName=fileName.substring(fileName.lastIndexOf(".")+1);
//新的图片名=获取时间戳+"."图片扩展名
String newFileName=String.valueOf(System.currentTimeMillis())+"."+extensionName;
System.out.println(picUrl);
//将图片上传到服务器
//saveFile(newFileName,filedata);
saveFile(request,fileName,filedata);
//将图片名称保存至数据库
photoService.insert(fileName,filedata.getBytes());
//图片路径
String realPath=request.getSession().getServletContext().getRealPath(picUrl+"\\"+newFileName);
System.out.println("cddd:"+realPath);
}
JSONArray jsonArray=new JSONArray();
for(int i=3;i<4;i++){
Photo p=photoService.getPhotoById(new BigDecimal(i));
jsonArray.add(p);
}
return jsonArray.toString();
}
private void saveFile(HttpServletRequest request,String newFileName, MultipartFile filedata) {
//根据配置文件获取服务器图片存放路径
String saveFilePath=picUrl;
//构建文件目录
File tempFile=new File(saveFilePath);
if(!tempFile.exists()){
tempFile.mkdirs();
}
//保存文件到服务器
FileOutputStream fos;
try {
fos = new FileOutputStream(saveFilePath+"\\"+newFileName);
fos.write(filedata.getBytes());
//fos.flush();
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
图片上传的jsp页面代码如下:
[html] view plain copy print?
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
upLoadFile
(2)将图片从数据库中读取出来,输出到页面上显示
首先用一个Controller来返回显示图片的页面:
[java] view plain copy print?
//跳转到图片显示的页面
@RequestMapping(value="/toImageDisplay")
public String toImageDisplay(){
return "waterfullPic";
}
我的waterfullPic.jsp页面如下:
[html] view plain copy print?
"/Login_ssm_mav_picbyte/user/toLookImage?id=13"> src即为向/Login_ssm_mav_picbyte/user/toLookImage路径发出请求,而这个请求对应的Controller处理代码如下:
[java] view plain copy print?
//将图片输出到页面进行显示
@RequestMapping(value="/toLookImage",method = RequestMethod.GET)
public void lookImage(@PathParam("id")int id,HttpServletRequest request,HttpServletResponse response,Model model){
HttpSession seesion = request.getSession();
Photo photo=photoService.getPhotoById(new BigDecimal(id));
byte[] data=photo.getPhotoData();
response.setContentType("img/jpeg");
response.setCharacterEncoding("utf-8");
try {
OutputStream outputStream=response.getOutputStream();
InputStream in=new ByteArrayInputStream(data);
int len=0;
byte[]buf=new byte[1024];
while((len=in.read(buf,0,1024))!=-1){
outputStream.write(buf, 0, len);
}
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我是通过请求中传递过来的id到数据库中取出图片。在这里我遇到了两个注解@PathParam和@RequestParam,我查了下这两个的区别,这里就不再介绍了,不懂的话可以再去网上查查。 这样便可以将图片从数据库中读取出来显示到页面上了。 另外瀑布墙要随着滚动条滚动动态加载图片,我在js中实现了这个功能,那么js中该如何设计这些Img的src呢? 我可能用了比较笨拙的办法,我是先把要显示的图片从数据库中全部读取出来,取出他们的数据,然后json格式的格式传递到前台在前台从json字符串中取出id再设置到请求路径中去。
首先我用一个Controller来从数据库中读取出具,代码如下:
[java] view plain copy print?
//从数据库中读取信息转换成json格式传递到前台
@RequestMapping("/picToJsonReturn.do")
@ResponseBody
public String picToJsonReturn(HttpServletRequest request,Model model){
JSONArray jsonArray=new JSONArray();
for(int i=13;i<35;i++){
Photo p=photoService.getPhotoById(new BigDecimal(i));
jsonArray.add(p);
}
return jsonArray.toString();
}
前台接收的js代码如下:
[javascript] view plain copy print?
function sscroll(){
var pic;//原来要把变量定义在这里,之前定义在外面,就会出现undefined的错误
$.ajax({
async:false,
type:'get',//get是获取数据,post是带数据的向服务器发送请求
//url:'addAction.do',
url:'picToJsonReturn.do',
dataType:'json',
success:function(data){
pic=eval(data);//转换成js对象
},
error:function(data){
alert("JSON数据获取失败,请联系管理员!");
}
});
url:'picToJsonReturn.do',这一行就代表向后台发出请求,data即为后台传递过来的json字符串,这里要主要变量要定义在funcation中不然打印alert(pic)时便会出现Object Object这些,下面是我的动态显示照片墙的js的代码:
[javascript] view plain copy print?
window.οnlοad=function(){/*当页面加载的时候调用函数*/
setInterval(function(){window.onscroll = sscroll();},1000);
waterfall('main','pin');
window.οnscrοll=sscroll();
}
/*之前将函数写在里面时一直实现不了,现在这样写在外面便可以了。*/
function sscroll(){
var pic;//原来要把变量定义在这里,之前定义在外面,就会出现undefined的错误
$.ajax({
async:false,
type:'get',//get是获取数据,post是带数据的向服务器发送请求
//url:'addAction.do',
url:'picToJsonReturn.do',
dataType:'json',
success:function(data){
pic=eval(data);//转换成js对象
},
error:function(data){
alert("JSON数据获取失败,请联系管理员!");
}
});
var dataInt={'data':[{'src':'img1.jpg'},{'src':'img2.jpg'},{'src':'img3.jpg'},{'src':'img4.jpg'},{'src':'img5.jpg'},{'src':'img6.jpg'}]};
if(checkscrollside()){
var oParent=document.getElementById('main');
for(var i=0;i
var oPin=document.createElement('div');//添加元素节点
oPin.className='pin';
oParent.appendChild(oPin);
var oBox=document.createElement('div');
oBox.className='box';
oPin.appendChild(oBox);
var oImg=document.createElement('img');
//oImg.src='/Login_ssm_mav_picbyte/static/pic/'+dataInt.data[i].src;
oImg.src=src='/Login_ssm_mav_picbyte/user/toLookImage?id='+pic[i].photoId;
//oImg.src='http://localhost:9988/pic/'+pic[i].photoName;
oBox.appendChild(oImg);
}
waterfall('main','pin');
}
}
function waterfall(parent,pin){
var oParent=document.getElementById(parent);//父级对象
var aPin=getClassObj(oParent,pin);//获取存储pin的数组的pin
var iPinW=aPin[0].offsetWidth;//一个块框pin的宽
var num=Math.floor(document.documentElement.clientWidth/iPinW);//每行中能容纳的pin的个数[窗口的宽度除以一个块框的宽度]
oParent.style.cssText='width:'+iPinW*num+'px;margin:0 auto;';//设置父级居中样式:定宽+自动水平外边距
var pinHArr=[];//用于存储没列中的所有块框相加的高度
for(var i=0;i
var pinH=aPin[i].offsetHeight;
if(i
pinHArr[i]=pinH;//第一行中的num个块框pin先添加进数组pinHrr
}else{
var minH=Math.min.apply(null,pinHArr);//数组pinHArr中的最小值
var minHIndex=getminHIndex(pinHArr,minH);//获取高度最小的pin的index
aPin[i].style.position='absolute';//设置绝对偏移
aPin[i].style.top=minH+'px';
aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';
pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加了快框后的列高
}
}
}
//获取高度最小的pin 的index
function getminHIndex(arr,minH){
for(var i in arr){
if(arr[i]==minH){
return i;
}
}
}
/*通过父级和子元素的class名称获取该同类子元素的数组*/
function getClassObj(parent,className){
var obj=parent.getElementsByTagName('*');//获取父类元素的所有子元素
var pinS=[];//创建一个数组,用于收集子元素
for(var i=0;i
if(obj[i].className==className){
pinS.push(obj[i]);
}
}
return pinS;
}
function checkscrollside(){
var oParent=document.getElementById('main');
var aPin=getClassObj(oParent,'pin');
var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);
//创建【触发添加块框的的函数waterfall()】的高度:最后一个块框的与网页顶部的距离+自身高的一半(未滚到底便开始加载)
//网页中获取滚动条卷去部分的高度
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
var documentH=document.documentElement.clientHeight;//页面高度
return (lastPinH
}
看我funcation sscroll()中会随着滚动条滚动增加Img标签,该标签的src我写的是:oImg.src=src='/Login_ssm_mav_picbyte/user/toLookImage?id='+pic[i].photoId; 即从后台传递过来的json字符串中取出id。
整个图片展示的工程也就大致是上面描述的那样,可能我描述的比较乱。
另外要注意很多关于路径的问题,我总是会碰到访问路径的问题。
比如说访问webapp下面的static/pic文件夹下的图片,访问路径应该是:/Login_ssm_mav_picbyte/static/pic/
后面我会再想想之前想的另一种方案,即将图片存在我的E盘中,而数据库中只保存图片的名字。
更多精彩内容,请关注博主公众号