做的时候查看了很多博客,也遇到了很多不经意的问题,如下
1,关于上传路径的问题,由于springboot内置tomcat,打包之后为jar包,无法上传文件至项目内部,查找网上有很多解决方案,未见生效,下面为我的解决方案:上传至服务器默认文件夹:
代码如下:
首先是设置上传文件的查看路径,相当于配置路径
${my.upload.base.dir}为在application.properties的配置,如下
#上传路径 windows端的配置,用于本地
my.upload.base.dir=D:/upload/
#linux服务器端配置,选择自己想上传的文件夹
my.upload.base.dir=/root/upload/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
@Configuration
public class WebSecurityConfig extends WebMvcConfigurerAdapter {
@Value("${my.upload.base.dir}")
private String uploadBaseDir;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/ImgFile/**").addResourceLocations("file:"+uploadBaseDir+"ImgFile/");
super.addResourceHandlers(registry);
}
}
所有的配置都完成,后面为功能代码:
页面代码:
<label><!-- 可以选取一张或者多种图片上传 multiple -->
<input type="file" name="glycosylated_hemoglobin" multiple accept="image/jpg,image/jpeg,image/png,image/bmp">
<span>上传检验单</span>
</label>
$(function(){
$("input[type='file']").change(function(){
var files = $(this).prop('files');//获取到文件列表
if (files.length == 0) {
alert('请选择文件');
} else {
//判断选择的文件大小
var fileSize = 0;
for(var i = 0; i < files.length; i++) {
fileSize += files[i].size;
}
var size = fileSize/1024/1024;//此处以兆为单位
if(size>50){
alert("附件不能大于50M");
target.value="";
return; //阻止submit提交
}
$(this).attr("disabled","disabled");
saveAndUpdateFile($(this),files);
}
})
})
var saveAndUpdateFile = function (that,files){
var imgSrc = []; //图片路径
var imgFile = []; //文件流
var imgName = []; //图片名字
var formData = new FormData();
formData.append("name", that.attr("name"));
for(var i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
var fileList = files;
for(var i = 0; i < fileList.length; i++) {
var imgSrcI = getObjectURL(fileList[i]);
imgName.push(fileList[i].name);
imgSrc.push(imgSrcI);
imgFile.push(fileList[i]);
}
var url = "/record/uploadImg?version="+Math.random();
$.ajax({
type:'post',
url:url,
data:formData,
async: false,
/**
*必须false才会自动加上正确的Content-Type
*/
contentType: false,
/**
* 必须false才会避开jQuery对 formdata 的默认处理
* XMLHttpRequest会对 formdata 进行正确的处理
*/
processData: false,
success: function (result) {
that.removeAttr("disabled");
if(result.statusCode==200){
//这个页面主要用于不刷新页面时回写图片的功能,拿到dom file回写在页面,不用可以不要,后面会有刷新后台回传回写操作
addNewContent(that.parent().parent().find(".images-box"),imgSrc,imgName,imgFile,result.divid,that.attr("name"));
}
},
error: function () {
}
});
}
//主要用于未保存不刷新界面时回写已经上传过的图片
function addNewContent(that,imgSrc,imgName,imgFile,ids,name){
var id = ids.split(":");
for(var a = 0; a < imgSrc.length; a++) {
that.append('<div id='+id[a+1]+' class="img"><a href=' + imgSrc[a] + ' target="_blank"><img src=' + imgSrc[a] + ' class="" title=' + imgName[a] + ' alt=' + imgName[a] + ' ></a>'
+' <img src="/images/omit.png" class="delete-img" onclick="deleteImage('+id[a+1]+','+name+')"></div>');
}
}
//本地 不包含后台图片预览路径
function getObjectURL(file) {
var url = null;
if(window.createObjectURL != undefined) { // basic
url = window.createObjectURL(file);
} else if(window.URL != undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if(window.webkitURL != undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
}
下面是controller代码:
使用ResourceLoader ,需要这行代码,img标签图片回写时用
private final ResourceLoader resourceLoader;
@Autowired
public UploadFileUtil(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@RequestMapping("/uploadImg")
@ResponseBody
public BJUIResult uploadImg(
@RequestParam("files") MultipartFile[] files, //多文件上传
@RequestParam("name") String name,
HttpServletRequest request) {
List<Eye> imgs = new ArrayList<Eye>();
Result ret = new Result();
try {
//判断file数组不能为空并且长度大于0
if(files!=null&&files.length>0){
//上传files数组
//循环获取file数组中得文件
for(int i = 0;i<files.length;i++){
MultipartFile file = files[i];
String fileName = file.getOriginalFilename();
String uploadPath = "imgFile";
//realPath:获取Web项目的全路径
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
String directory = uploadBaseDir + uploadPath + File.separator + df.format(new Date()) + File.separator;
UploadFileUtil fileUtil = new UploadFileUtil();
String newPicName = fileUtil.saveFile(request, file, directory, fileName);
logger.info("---------------------上传的查看图片路径----------------------"+ uploadPath+File.separator+df.format(new Date())+ File.separator +newPicName);
String viewPath = uploadPath+File.separator+df.format(new Date())+ File.separator +newPicName;
Eye img = new Eye();
img.setName(name);
img.setImgUrl(viewPath);//对象保存一下图片浏览地址
img.setImgName(fileName);
img.setUpdateTime(new Date());
img.setCreateId(1);
img.setCreateTime(new Date());
img.setNowStatus(1); //已上传
img.setType(0);
imgs.add(img);
//保存文件
}
}
service.saveEyeImg(imgs);//保存方法我就不提供了,自己去保存
String ids = "";
//用于不刷新页面回写,然后赋值,如果情况允许,应该上传完成页面是要刷新的,所以不用考虑这个情况,后面讲了回写
for(Eye img : imgs) {
ids+=":"+img.getId();
}
ret.setDivid(ids);
ret.setMessage("操作成功!");
ret.setStatusCode(200);
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public String saveFile(HttpServletRequest request, MultipartFile file, String realPath, String newPicName) throws Exception {
// 判断文件是否为空
if (!file.isEmpty()) {
try {
if (file.getSize() != 0) {
String originalFileName = file.getOriginalFilename();
// 新的图片名称 需要就可以加,由于服务器同文件夹对于传同名的会被覆盖,故需要uuid区分一下
newPicName = originalFileName.substring(0,originalFileName.lastIndexOf("."))+UUID.randomUUID()+
originalFileName.substring(originalFileName.lastIndexOf("."));
// 新图片,写入磁盘
File f = new File(realPath, newPicName);
if (!f.exists()) {
// 先创建文件所在的目录
f.getParentFile().mkdirs();
}
file.transferTo(f);
}
return newPicName;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
return "";
}
这么多代码就可以完成上传操作了,然后是回写上传的图片,一般是上传结束会进行刷新,然后回写图片,我上面的代码有一段js是可以直接回写本地图片,在不刷新情况下,刷新后显示上传的图片,无缝衔接,大家看自己需求了;
后台回写代码如下:
<a href="/record/queryPic?id=${img.id}" target="_blank">
<img src="/record/getFile?id=${img.id}" class="" title="${img.imgName}" alt="${img.imgName}">
</a>
由于我们有个需求是,点击图片放大,到一个新的页面,又不能直接给权限让用户直接访问地址,存在图片泄露的风险,
如果你的图片不保密,可以直接,下面的代码通过链接访问,可以成功
<a href="${img.imgUrl}" target="_blank">
<img src="${img.imgUrl}" class="" title="${img.imgName}" alt="${img.imgName}">
</a>
,controller去访问,img标签和a标签点击的方法不同,代码如下:
//显示图片的方法 img标签显示图片的方法
//<img src="/record/getFile?id=${img.id}" class="" title="${img.imgName}" alt="${img.imgName}">
@RequestMapping("/getFile")
@ResponseBody
public ResponseEntity<?> getFile(@RequestParam("id") Integer id) {
Eye img = service.getEyeImgByImgId(id);
try {
return ResponseEntity.ok(resourceLoader.getResource(
"file:" + Paths.get(uploadBaseDir + img.getImgUrl()).toString()));
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
/*
* 获取图片并显示在页面 a标签
* @return
* @throws SQLException
* <a href="/record/queryPic?id=${img.id}" target="_blank">
*/
@RequestMapping(value = "queryPic")
public void queryPic(@RequestParam("id") Integer id,HttpServletRequest request, HttpServletResponse response) throws IOException {
Eye img = service.getEyeImgByImgId(id);
if (img.getImgUrl().toString() != null){
response.setContentType("image/jpeg");
FileInputStream is = null;
File filePic = new File(uploadBaseDir + img.getImgUrl().toString());
try {
is = new FileInputStream(filePic);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (is != null){
int i = is.available(); // 得到文件大小
byte data[] = new byte[i];
is.read(data); // 读数据
is.close();
response.setContentType("image/jpeg"); // 设置返回的文件类型
OutputStream toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象
toClient.write(data); // 输出数据
toClient.close();
}
}
}
ok啦,就这么多代码,没啦,对了,我们前面用的freemaker框架,和jsp一样的