现在,我们需要使用springboot和layui来上传图片或者文件,springboot已经集成了文件上传功能,我们可以直接开始使用。
本次的需求是:在表单中,点击按钮上传图片,上传成功则在按钮旁边把上传的图片显示出来。
视图层
上传文件之后,需要将上传后获取的文件url路径放到一个隐藏的input中,在提交的时候提交给数据库存起来,所以,我们先在表单中放一个按钮和一个隐藏的img标签
<form id="taskAdd" class="layui-form" method="post" style="padding: 20px"
autocomplete="off">
<div class="layui-form-item">
<label class="layui-form-label">问题描述</label>
<div class="layui-input-block">
<textarea type="text" id="taskdesc" name="taskdesc" lay-verify="text"
autocomplete="off" placeholder="请输入问题描述" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">上传照片</label>
<button type="button" class="layui-btn" id="uploadimg">
<i class="layui-icon"></i>上传图片
</button>
<img id="show_up_img" style="display: none; width: 200px;height: 100%;" src="" />
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="layui-btn" lay-submit=""
lay-filter="cateSubBtn">立即提交</button>
</div>
</div>
</form>
其中的重点在下方,可以看到,我们放入了一个按钮,一个img标签,并且为img标签设置了默认不显示。
<div class="layui-form-item">
<label class="layui-form-label">上传照片</label>
<button type="button" class="layui-btn" id="uploadimg">
<i class="layui-icon"></i>上传图片
</button>
<img id="show_up_img" style="display: none; width: 200px;height: 100%;" src="" />
</div>
接下来,使用js来请求接口并且上传文件,上传成功后res为服务器返回的值,包括了url和实际路径,然后接着把上面的img标签填充src并且让他显示即可。
//执行实例
var uploadInst = upload.render({
elem: '#uploadimg' //绑定元素
,url: '/fileUpload' //上传接口
,accept: 'file'
,method: 'POST'
,done: function(res){
//上传完毕回调
$("#show_up_img").attr("src","/upload-files/"+res.data.url).css("display","");
layer.alert(res.data.url + " " + res.data.path);
}
,error: function(){
layer.alert("上传失败!图片限制10MB内");
//请求异常回调
}
});
视图的显示以及提交逻辑已经写好了,接下来,我们需要在后端处理上传的文件。
控制层
我们先设置一个上传的目录,也就是一个上传到服务器的路径,这里我先设置为D盘的一个文件夹。(当然,服务器大都是运行linux的,而linux和win的文件系统稍有不同,这部分后面再说)
D://upload-files//
在处理文件之前,我们要先配置一下路径映射,将请求的/upload-files
映射到我们刚刚设置的文件夹
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { // 映射资源url与本地资源路径
registry.addResourceHandler("/upload-files/**").addResourceLocations("file:D:/upload-files/");
}
}
接着,我们写一个post方法,来处理上传的文件,其中,为了避免中文文件名称的编码问题,将上传的文件名称截取到最后一个小数点,然后通过时间戳加上随机数的方式来避免文件名重复。
String file_suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."),file.getOriginalFilename().length());
Random rand = new Random();
fileNameString = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_"+ (rand.nextInt(1000)+1) + file_suffix;
pathString = "D://upload-files//" + fileNameString;
然后使用一个Map来返回layui所需要的json的数据
Map<String,Object> map = new HashMap<>();
Map<String,String> datas = new HashMap<>();
datas.put("path", pathString);
datas.put("url",fileNameString);
//状态码如果成功返回0
map.put("code", "0");
//错误代码
map.put("msg", "");
//返回路径
map.put("data", datas);
完整代码如下:
@PostMapping("/fileUpload")
public Map<String,Object> fileUpload(@RequestParam(value = "file") MultipartFile file, Model model, HttpServletRequest request) {
System.out.println(file);
String pathString = null;
String fileNameString = null;
if(file!=null) {
String file_suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."),file.getOriginalFilename().length());
Random rand = new Random();
fileNameString = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_"+ (rand.nextInt(1000)+1) + file_suffix;
pathString = "D://upload-files//" + fileNameString;
}
try {
assert pathString != null;
File files=new File(pathString);
//打印查看上传路径
System.out.println(pathString);
if(!files.getParentFile().exists()){
files.getParentFile().mkdirs();
}
file.transferTo(files);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Map<String,Object> map = new HashMap<>();
Map<String,String> datas = new HashMap<>();
datas.put("path", pathString);
datas.put("url",fileNameString);
//状态码如果成功返回0
map.put("code", "0");
//错误代码
map.put("msg", "");
//返回实体对象集合
map.put("data", datas);
return map;
}
优化
在图片上传成功之前,我们可以添加一个正常上传的状态,在网络不好的情况下就会显示加载状态
写一个函数,然后调用它
function showloading(stat) {
if (stat) {//如果是true则显示loading
// console.log(t);
loading = layer.load(1, {
shade: [0.3, '#000'], //0.1透明度的白色背景
content:'<p style="position: relative;left: -50px;">图片上传中,请耐心等待...
',
success: function (layerContentStyle) {
layerContentStyle.find('.layui-layer-content').css({
'padding-top': '50px',
'text-align': 'left',
'line-height':'30px',
'color':'#fff',
'width': '300px'
})
}
});
}else{//如果是false则关闭loading
// console.log("关闭loading层:" + t);
layer.closeAll('loading');
}
}
接着修改上传逻辑的代码,改成下面这个样子即可
var uploadInst = upload.render({
elem: '#uploadimg' //绑定元素
,url: '/fileUpload' //上传接口
,accept: 'file'
,method: 'POST'
,before: function(input) {// 上传完成之前
//返回的参数item,即为当前的input DOM对象
showloading(true)
}
,done: function(res){
//上传完毕回调
showloading(false);
$("#show_up_img").attr("src","/upload-files/"+res.data.url).css("display","");
layer.alert(res.data.url + " " + res.data.path);
}
,error: function(){
showloading(false);
layer.alert("上传失败!图片限制10MB内");
//请求异常回调
}
});
补充
中途遇到过一次上传失败的情况,排查后发现是因为Springboot对上传的文件做了一个默认的限制,我们在yml配置文件里面修改一下即可
上传文件到jar包相对目录
使用下面的方式可以获取到当前jar包所运行的目录
String basePath = new ApplicationHome(this.getClass()).getSource().getParentFile().getPath()
2 条评论
直接搞Vue呗,layui现在用的人也很少了,再对接一下对象存储。美滋滋
准备搞一下uniapp,也是vue语法