前端使用的是开源框架layui。layui提供了一个上传文件的组件,使用方式如下:
<script>
layui.use('upload',function(){
var $=layui.jquery
,upload=layui.upload;
//普通图片上传
var uploadInst=upload.render({
elem:'#test1'
,url:'/addPhoto/'
,before:function(obj){
//预览本地文件示例
obj,preview(function(index,file,result){
$('#demo1').attr('src',result);
});
}
,done:function(res){
//如果上传失败
if(res.code>0){
return layer.msg('上传失败');
//上传成功
layer.msg('上传成功');
}
});
script>
以上就是前端部分处理的代码。但是非常值得一提的是,如果只写了前端代码,图片是上传不上去的,因为它必须要返回一个接口url,在接口里进行处理。以下是layui文档里关于上传接口的定义。
这里的难点就在于我从来没有写过接口,对于javascript不是十分熟悉,也不太会写Ajax。所以我一度在接口这里纠结里很久,刚开始甚至以为接口是写一个文件夹的路径,然后就会把上传的图片保存到写的路径中。后来才发现接口就是一个url。于是我的接口写的就是/addPhoto/
。然后再SpringBoot里的控制器Controller里获取到这个url,然后进行操作。
//上传照片
@RequestMapping(value = "/addPhoto",method = RequestMethod.POST)
public @ResponseBody String uploadImg(@RequestParam("file") MultipartFile file,HttpSession session,
HttpServletRequest request) {
Photo photo=new Photo();
String str="";
String league_id=request.getSession().getAttribute("leagueID").toString();
System.out.println("联赛id:"+league_id);
String url=request.getRequestURI();
System.out.println("URL:"+url);
try {
if(null!=file){
//获得当前项目所在路径
String pathRoot=request.getSession().getServletContext().getRealPath("");
System.out.println("当前项目所在路径:"+pathRoot);
//生成uuid作为文件名称
String uuid=UUID.randomUUID().toString().replaceAll("-","");
System.out.println("文件名称:"+uuid);
//获得文件类型(判断如果不是图片文件类型,则禁止上传)
String contentType=file.getContentType();
System.out.println("文件类型:"+contentType);
//获得文件后缀名称
String imageName=contentType.substring(contentType.indexOf("/")+1);
System.out.println("文件后缀名称:"+imageName);
String filePath="/Users/hurley/Desktop/footballleague-managementsystem/src/main/resources/static/upload/images/";
//根据日期来创建对应的文件夹
String datePath=new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
System.out.println("日期:"+datePath);
//根据id分类来创建对应的文件夹
String leagueIdPath=league_id+"/";
//日期
/*String path=filePath+datePath;*/
//联赛id
String path=filePath+leagueIdPath;
//如果不存在,则创建新文件夹
File f=new File(path);
if(!f.exists()){
f.mkdirs();
}
//新生成的文件名称
String fileName=uuid+"."+imageName;
System.out.println("新生成的文件名称:"+fileName);
session.setAttribute("fileName",fileName);
//图片保存的完整路径
String pathName=path+fileName;
System.out.println(pathName);
//获取所属联赛ID
int leagueID=Integer.parseInt(league_id);
//图片的静态资源路径
String staticPath="/upload/images/"+leagueID+"/"+fileName;
System.out.println("静态资源路径:"+staticPath);
//复制操作
//将图片从源位置复制到目标位置
file.transferTo(new File(pathName));
str = "{\"code\": 0,\"msg\": \"\",\"data\": {\"src\":\"" + "pic/"+datePath+fileName + "\"}}";
photo.setStaticPath(staticPath); //将图片保存的静态资源路径插入数据库
photo.setLeagueID(leagueID); //将所属联赛ID插入数据库
photo.setUploadDate(datePath); //将上传日期插入数据库
photo.setDestFile(pathName); //将完整路径插入数据库
photo.setFileName(fileName); //将最后保存的完整文件名插入数据库
photoRepository.save(photo);
}
else{
System.out.println("文件为空");
}
}catch (IOException e){
e.printStackTrace();
}finally {
return str;
}
}
首先JavaScript里url是通过post的方式上传图片,所以在Controller里是PostMapping("/addPhoto")
的方式对获取到的url进行处理。
因为我目前还不知道如何将本地的图片上传保存到服务器例如七牛云存储上,所以该项目的图片都是保存到项目指定的文件夹中。
先通过@RequestParam("file") MultipartFile file
接收到上传的文件,然后判断如果文件不为空,那么
//获取当前项目所在路径
String pathRoot=request.getSession().getServletContext().getRealPath("");
System.out.println("当前项目所在路径:"+pathRoot);
//生成uuid作为文件名称
String uuid=UUID.randomUUID().toString().replaceAll("-","");
System.out.println("文件名称:"+uuid);
//获得文件类型(判断如果不是图片文件类型,则禁止上传)
String contentType=file.getContentType();
System.out.println("文件类型:"+contentType);
//获得文件后缀名称
String imageName=contentType.substring(contentType.indexOf("/")+1);
System.out.println("文件后缀名称:"+imageName);
//这就是我要保存的路径,在项目工程里
String filePath="/Users/hurley/Desktop/footballleague-managementsystem/src/main/resources/static/upload/images/";
//本来是想根据日期分类创建文件夹的,但是因为后来是根据不同联赛的id进行分类显示,所以后来就根据联赛id创建对应的文件夹
//根据日期来创建对应的文件夹
String datePath=new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
System.out.println("日期:"+datePath);
//根据id分类来创建对应的文件夹
String leagueIdPath=league_id+"/";
//联赛id
String path=filePath+leagueIdPath;
//如果不存在,则创建新文件夹
File f=new File(path);
if(!f.exists()){
f.mkdirs();
}
//新生成的文件名称
String fileName=uuid+"."+imageName;
System.out.println("新生成的文件名称:"+fileName);
session.setAttribute("fileName",fileName);
//图片保存的完整路径
String pathName=path+fileName;
System.out.println(pathName);
//获取所属联赛ID
int leagueID=Integer.parseInt(league_id);
//图片的静态资源路径
String staticPath="/upload/images/"+leagueID+"/"+fileName;
System.out.println("静态资源路径:"+staticPath);
//复制操作
//将图片从源位置复制到目标位置
file.transferTo(new File(pathName));
str = "{\"code\": 0,\"msg\": \"\",\"data\": {\"src\":\"" + "pic/"+datePath+fileName + "\"}}";
photo.setStaticPath(staticPath); //将图片保存的静态资源路径插入数据库
photo.setLeagueID(leagueID); //将所属联赛ID插入数据库
photo.setUploadDate(datePath); //将上传日期插入数据库
photo.setDestFile(pathName); //将完整路径插入数据库
photo.setFileName(fileName); //将最后保存的完整文件名插入数据库
photoRepository.save(photo);
其实主要就是通过接受到的上传的文件,获取该文件的一些属性,例如文件名称,文件类型(后缀名),还有文件上传日期等。然后我这里手动为其指定了保存路径的前半部分,即保存在我工程目录的src/main/resources/static/upload/images路径下,然后根据所属联赛id的不同,在该路径下创建不同id的文件夹以进行分类,对之后显示图片起到帮助。
综上,通过在接口里写入url,然后在后端获取这个url,就可以执行将本地文件复制到指定路径保存的操作,同时把相关路径等信息保存进数据库。而在查询的时候,只需要根据所属联赛id,在数据库中找出所有所属联赛id为选中的联赛id的图片,然后再查询每个路径保存的路径,通过thymeleaf就可以将所有图片显示在页面中。
现在还缺少的功能是修改和删除。修改的话图片可能不太需求修改,删除的话我还不太会,因为既需要在保存的路径中把保存的图片删除,又需要在数据库中把保存的该图片的信息删除。目前的想法是还是通过按钮注解url的方式,在Java后端里通过Java对于文件的操作等方式,通过给出图片的路径,进行删除,然后再在数据库中查询出该图片的路径,delete整个该图片的对象。
目前还有一个缺点就是上传一张图片后,不能立即显示在页面中,图片会成裂掉的状态,重新编译后即可显示。但是图片路径都是正确的,目前还不知道什么原因。
在这个功能完全实现之后,我打算在尝试将图片上传保存到云服务器端,这样就更符合逻辑。