在一个应用系统里,会有上传本地文件到系统服务器里或从系统服务器查看、下载有关文件到本地的需要。这里只对自己了解到的做一个总结
文件上传
这里是把本地文件上传到服务器文件目录,而不是放到项目目录里。
前端用的bootstrap和Jquery,上传文件界面显示在是模态框里
//文件上传
<input id="uploadFile" type="file" name="file" style="margin-left: 90px; margin-top: 10px">
<!-- 模态框 -->
<div class="modal fade" id="newImg">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">上传新的流程图</div>
<!-- <form class="form-horizontal"> -->
<div class="modal-body">
<div class="form-group">
<label for="inputEmail" class="col-sm-2 control-label">添加描述</label>
<div class="col-sm-10">
<input id="describle" type="text"
class="form-control list-inline" />
</div>
</div>
<div class="form-group">
<label class="control-label" style="margin-left: 30px">待上传的文件</label>
<div style="margin-left: 20px">
<label class="control-label">输入记录id</label>
<input type="text" id="relId_ajax" name="relId_ajax">
<input id="uploadFile" type="file" name="file" style="margin-left: 90px; margin-top: 10px">
</div>
</div>
<div class="modal-footer">
<button id="back_btn" class="btn btn-danger" data-dismiss="modal">取消</button>
<button class="btn btn-success" onclick="submit_btn()" data-dismiss="modal">上传</button>
</div>
</div>
<!-- </form> -->
</div>
</div>
</div>
点击上传之后。调用JS方法使用ajax方法进行上传。上传成功之后,接收到后端返回的信息,并再次调用ajax请求对这些信息进行处理。这些信息后面会提到
//上传新的流程图(单文件上传,ajax方式)
function submit_btn(){
var relId = $("#relId_ajax").val();
var fileDescribe = $("#describle").val();
var file = $("#uploadFile")[0].files[0];
var formData = new FormData();
formData.append("file", file);
formData.append("relId", relId);
formData.append("fileDescribe", fileDescribe);
$.ajax({
dataType : "JSON",
contentType : "application/json;charset=UTF-8",
type : "POST",
data : formData,
url : "/hzsh/eomc-front/file/multiUpload",
processData : false, // 使数据不做处理
contentType : false, // 不要设置Content-Type请求头
success : function(result) {
console.log(result)
console.log(result.msg)
var JsonData = JSON.parse(result.data) //将后端传回的json数组字符串转换为json对象
//[{"fileName":"compareWithAll.PNG","id":"4b267540-1d97-4703-85b8-6522ee26843f"}]
var imgId = JsonData[0].id;
console.log(imgId);
$.ajax({
type:"post",
url:"/hzsh/eomc-zzhj/nyglms/updateImg",
data:{"imgId":imgId},
success:function(result){
console.log("进行流程图更新")
if(result.code){
alert("上传成功")
}else{
alert("上传失败")
}
}
})
},
error : function() {
console.log("上传出错");
}
})
}
效果如图:(这里我上传的是图片)
点击上传之后,会先将文件保存到数据库的附件表里,这张表就是对上传的文件元数据做统一的管理,包括文件类型、文件原名、文件大小、上传时间、上传用户等等。因为考虑到文件安全问题,上传的文件经过后端处理,存到服务器端文件目录里的文件名是一串随机字符串序列。
@RequestMapping("/file/multiUpload")
public String multiUpload(HttpServletRequest request, HttpServletResponse response,HttpSession session) {
try {
String userName = (String) session.getAttribute("userName");
String fileDescribe = request.getParameter("fileDescribe");
String relId = request.getParameter("relId");
String sort = request.getParameter("sort");
log.info("文件描述" + fileDescribe);
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
boolean result = true;
String retMsg = "";
JSONArray retDataArray = new JSONArray();
for (int i = 0; i < files.size(); i++) {
MultipartFile file = files.get(i);
if (file.isEmpty()) {
retMsg += "第" + (i + 1) + "个文件为空";
continue;
}
String fileName = file.getOriginalFilename();
//定义附件表对象,用于将上传的文件元数据写入附件表
CommAttachEntity commAttachEntity = new CommAttachEntity();
commAttachEntity.setId(UUID.randomUUID().toString());
commAttachEntity.setRealName(fileName);
commAttachEntity.setEncName(commAttachEntity.getId());
int extendIndex = fileName.indexOf(".");
if(extendIndex < 0) {
extendIndex = 0;
}
commAttachEntity.setExtendName(fileName.substring(extendIndex));
if(CDataUtil.isPicture(fileName)) {
commAttachEntity.setFileType("图片");
}else if(CDataUtil.isDocument(fileName)) {
commAttachEntity.setFileType("文档");
}else {
commAttachEntity.setFileType("未知");
}
commAttachEntity.setFlgDel("0");
commAttachEntity.setFileSize(file.getSize() + "");
commAttachEntity.setCreateUser(userName);
commAttachEntity.setCreateDate(CDateTimeUtil.sysDateTime("yyyy-MM-dd HH:mm:ss"));
commAttachEntity.setRemark(fileDescribe);
commAttachEntity.setRelId(relId);
if(sort == null || sort.trim().equals("")) {
commAttachEntity.setSort(i + "");
}else {
commAttachEntity.setSort(sort);
}
//文件输出到本地
File dest = new File(EnvConstant.attachPath + commAttachEntity.getEncName());
try {
file.transferTo(dest);
log.info("第" + (i + 1) + "个文件上传成功(" + fileName + ")");
} catch (Exception e) {
log.error("第" + (i + 1) + "个文件上传失败(" + fileName + ")" + e.toString(), e);
result = false;
retMsg += fileName + ";";
}
//写入附件表
commAttachMapper.insert(commAttachEntity);
JSONObject retDataJson = new JSONObject();
retDataJson.put("id", commAttachEntity.getId());
retDataJson.put("fileName", fileName);
retDataArray.add(retDataJson);
}
System.out.println(retDataArray+"KKKKKKKKKKKKKKKKKKK");
if(result) {
System.out.println("上传成功");
return CIOUtil.buildRetMsg(true, "上传成功", retDataArray);
}else {
return CIOUtil.buildRetMsg(false, retMsg + " 文件上传失败", retDataArray);
}
}catch(Exception e) {
return CIOUtil.buildRetMsg(false, "文件上传出错", e.getMessage());
}
}
上面这段代码就是对前端发送来的文件进行处理,生成一些文件元数据保存到数据库对应的附件表里。附件表主键就是在这里生成的随机序列:UUID.randomUUID()
该接口代码处理完文件信息后一方面将文件元数据传到数据库,
//写入附件表
commAttachMapper.insert(commAttachEntity);
一方面将文件保存到对应的文件目录里,其中 EnvConstant.attachPath 是之前在类中定义好的
文件保存路径
//文件输出到本地
File dest = new File(EnvConstant.attachPath + commAttachEntity.getEncName());
file.transferTo(dest);
另一方面向前端返回一些信息
if(result) {
System.out.println("上传成功");
return CIOUtil.buildRetMsg(true, "上传成功", retDataArray);
}else {
return CIOUtil.buildRetMsg(false, retMsg + " 文件上传失败", retDataArray);
}
像前端返回的信息里包含了很重要的一项,就是随机生成的文件序列,也是文件上传后保存到服务器端目录里的文件加密名,这里的ajax请求是在点击“上传”后的JS方法里,是一个回调请求。
success : function(result) {
console.log(result)
console.log(result.msg)
var JsonData = JSON.parse(result.data) //将后端传回的json数组字符串转换为json对象
//[{"fileName":"compareWithAll.PNG","id":"4b267540-1d97-4703-85b8-6522ee26843f"}]
var imgId = JsonData[0].id;
console.log(imgId);
$.ajax({
type:"post",
url:"/hzsh/eomc-zzhj/nyglms/updateImg",
data:{"imgId":imgId},
success:function(result){
console.log("进行流程图更新")
if(result.code){
alert("上传成功")
}else{
alert("上传失败")
}
}
})
},
将随机生成的文件字符串序列保存到业务表里,作为外键和附件表进行关联。因为这里模拟的是特定业务的文件上传,业务里文件只有一个,所以上传文件属于更新操作。文件信息保存到业务表里始终只有一条记录。
@ResponseBody
@RequestMapping("/nyglms/updateImg")
public String updateNyglmsImg(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
// 获取CommAttachEntity对象流程图的Id信息
String imgId = request.getParameter("imgId");
// 将CommAttachEntity的流程图id信息写到nyglms表中
String userName = (String) session.getAttribute("userName");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar calendar = Calendar.getInstance();
String create_img_time = df.format(calendar.getTime());
EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = new EomcZzhjNyglmsEntity();
eomcZzhjNyglmsEntity.setId(1);
eomcZzhjNyglmsEntity.setCreateImgUser(userName);
eomcZzhjNyglmsEntity.setCreateImgTime(create_img_time);
eomcZzhjNyglmsEntity.setImgId(imgId);
int result = eomcZzhjNyglmsService.updateNyglmsImg(eomcZzhjNyglmsEntity);
if (result == 1) {
return CIOUtil.buildRetMsg(true, "上传成功", null);
} else {
return CIOUtil.buildRetMsg(false, "上传失败,请重新上传", null);
}
}
文件查看
此时,文件上传操作已经完成。当我们想在功能模块里查看已上传的文件时,只需发送请求到后端的业务表里获取唯一的文件随机字符串序列,并将字符串序列和文件保存路径进行拼接。这里使用IO流的方式将特定文件写出到前端页面。
@ResponseBody
@RequestMapping("/nyglms/queryImg")
public String queryNyglmsImage(HttpServletRequest request, HttpServletResponse response) {
// 获取最新上传的流程图片信息(从业务表中)
EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = eomcZzhjNyglmsService.queryNyglmsImg();
String imgId = eomcZzhjNyglmsEntity.getImgId();
System.out.println("查询流程图************************:"+imgId);
try {
File file = new File(EnvConstant.attachPath +imgId);
FileInputStream fis = new FileInputStream(file);
OutputStream out = response.getOutputStream();
long size = file.length();
byte[] temp = new byte[(int) size];
fis.read(temp, 0, (int) size);
fis.close();
byte[] data = temp;
response.setContentType("image/PNG");
// data = Base64.encodeBase64(data);
out.write(data);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return CIOUtil.buildRetMsg(true, "显示流程图成功", null);
}
前端代码:
<div>
<img id="Img" alt="" src="/nyglms/queryImg" style="height: 400px; width: 600px;" />
</div>
文件下载
可以从附件表获取文件随机字符串序列,也可以从业务表中获取。
这里从业务表中获取更容易一些(点击前端下载按钮,调用该后端接口)
/**
* a根据附件名称,下载附件
* @param fileName
* @param request
* @param response
* @param model
* @return
*/
@RequestMapping("/file/download")
public String download( HttpServletRequest request, HttpServletResponse response ,Model model) {
// 获取最新上传的流程图片信息(从业务表中)
EomcZzhjNyglmsEntity eomcZzhjNyglmsEntity = eomcZzhjNyglmsService.queryNyglmsImg();
String imgId = eomcZzhjNyglmsEntity.getImgId();
if(getImgId== null || getImgId.trim().equals("")) {
log.info("imgId为空,无法下载附件");
return CIOUtil.buildRetMsg(false, "imgId不能为空", null);
}
//设置为png格式的文件
setHeader(request, response, imgId);
byte[] buff = new byte[1024];
//创建缓冲输入流
BufferedInputStream bis = null;
OutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
//这个路径为待下载文件的路径
bis = new BufferedInputStream(new FileInputStream(new File(EnvConstant.attachPath + imgId)));
int read = bis.read(buff);
//通过while循环写入到指定了的文件夹中(这里指浏览器设置的目录文件夹)
while (read != -1) {
outputStream.write(buff, 0, buff.length);
outputStream.flush();
read = bis.read(buff);
}
} catch ( IOException e ) {
e.printStackTrace();
//出现异常返回给页面失败的信息
model.addAttribute("result","下载失败");
return "下载失败";
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//成功后返回成功信息
model.addAttribute("result","下载成功");
return CIOUtil.buildRetMsg(true, "下载成功", null);
}
private boolean setHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
try {
response.setContentType("application/octet-stream");
response.setHeader("content-type", "application/octet-stream");
String browser = request.getHeader("User-Agent");
if (-1 < browser.indexOf("MSIE 6.0") || -1 < browser.indexOf("MSIE 7.0")) {
// IE6, IE7 浏览器
response.addHeader("content-disposition", "attachment;filename="
+ new String(fileName.getBytes(), "ISO8859-1"));
} else if (-1 < browser.indexOf("MSIE 8.0")) {
// IE8
response.addHeader("content-disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8"));
} else if (-1 < browser.indexOf("MSIE 9.0")) {
// IE9
response.addHeader("content-disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8"));
} else if (-1 < browser.indexOf("Chrome")) {
// 谷歌
response.addHeader("content-disposition",
"attachment;filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));
} else if (-1 < browser.indexOf("Safari")) {
// 苹果
response.addHeader("content-disposition", "attachment;filename="
+ new String(fileName.getBytes(), "ISO8859-1"));
} else {
// 火狐或者其他的浏览器
response.addHeader("content-disposition",
"attachment;filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8"));
}
return true;
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
}