package cn.org.xinke.controller; import cn.org.xinke.annotation.Login; import cn.org.xinke.constant.FileTypeEnum; import cn.org.xinke.entity.User; import cn.org.xinke.util.CacheUtil; import cn.org.xinke.util.FileTypeUtil; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import org.apache.tika.Tika; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.*; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.*; /** * @description 文件服务器 * @author cinco * @date 2019-1-21 */ @Slf4j @CrossOrigin @Controller public class FileController { private static final String SLASH = "/"; @Value("${fs.dir}") private String fileDir; @Value("${fs.uuidName}") private Boolean uuidName; @Value("${fs.useSm}") private Boolean useSm; @Value("${fs.useNginx}") private Boolean useNginx; @Value("${fs.nginxUrl}") private String nginxUrl; @Value("${admin.uname}") private String uname; @Value("${admin.pwd}") private String pwd; @Value("${domain}") private String domain; /** * 登录页 * * @return */ @RequestMapping("/login") public String loginPage() { return "login.html"; } /** * 登录提交认证 * * @param user * @param session * @return */ @PostMapping("/auth") public String auth(User user, HttpSession session) { if (user.getUname().equals(uname) && user.getPwd().equals(pwd)) { session.setAttribute( "LOGIN_USER", user ); return "redirect:/"; } return "redirect:/login"; } /** * 首页 * * @return */ @Login @RequestMapping("/") public String index() { return "index.html"; } /** * 上传文件 * * @param file 文件 * @param curPos 上传文件时所处的目录位置 * @return Map */ @Login @ResponseBody @PostMapping("/file/upload") public Map upload(@RequestParam MultipartFile file, @RequestParam String curPos) { curPos = curPos.substring(1) + SLASH; if (fileDir == null) { fileDir = SLASH; } if (!fileDir.endsWith(SLASH)) { fileDir += SLASH; } // 文件原始名称 String originalFileName = file.getOriginalFilename(); String suffix = originalFileName.substring(originalFileName.lastIndexOf(".") + 1); String prefix = originalFileName.substring(0, originalFileName.lastIndexOf(".")); // 保存到磁盘 File outFile; String path; if (uuidName != null && uuidName) { path = curPos + UUID.randomUUID().toString().replaceAll("-", "") + "." + suffix; outFile = new File(fileDir + path); } else { int index = 1; path = curPos + originalFileName; outFile = new File(fileDir + path); while (outFile.exists()) { path = curPos + prefix + "(" + index + ")." + suffix; outFile = new File(fileDir + path); index++; } } try { if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdirs(); } file.transferTo(outFile); Map rs = getRS(200, "上传成功", path ); //生成缩略图 if (useSm != null && useSm) { // 获取文件类型 String contentType = null; try { contentType = new Tika().detect(outFile); } catch (IOException e) { e.printStackTrace(); } if (contentType != null && contentType.startsWith( "image/" )) { File smImg = new File(fileDir + "sm/" + path ); if (!smImg.getParentFile().exists()) { smImg.getParentFile().mkdirs(); } Thumbnails.of(outFile).scale(1f).outputQuality(0.25f).toFile(smImg); rs.put( "smUrl", "sm/" + path ); } } return rs; } catch (Exception e) { log.info(e.getMessage()); return getRS(500, e.getMessage()); } } /** * nginx转发 * * @param filePath * @return */ private String useNginx(String filePath) { if (nginxUrl == null) { nginxUrl = SLASH; } if (!nginxUrl.endsWith(SLASH)) { nginxUrl += SLASH; } String newName; try { newName = URLEncoder.encode( filePath, "utf-8" ); } catch (UnsupportedEncodingException e) { e.printStackTrace(); newName = filePath; } return "redirect:" + nginxUrl + newName; } /** * 获取源文件或者缩略图文件 * * @param p * @param download 是否下载 * @param response * @return */ private String getFile(String p, boolean download, HttpServletResponse response) { if (useNginx) { return useNginx(p); } if (fileDir == null) { fileDir = SLASH; } if (!fileDir.endsWith(SLASH)) { fileDir += SLASH; } outputFile(fileDir + p, download, response ); return null; } /** * 查看/下载源文件 * * @param p 文件全路径 * @param d 是否下载,1-下载 * @param response * @return */ @Login @GetMapping("/file") public String file(@RequestParam("p") String p, @RequestParam(value = "d", required = true) int d, HttpServletResponse response) { return getFile( p, d == 1 ? true : false, response ); } /** * 返回分享源文件或其缩略图页面或文件 * * @param sid * @param download 是否下载 * @param modelMap * @param response * @return */ private String returnShareFileOrSm(String sid, boolean download, ModelMap modelMap, HttpServletResponse response) { String url = null; if (!CacheUtil.dataMap.isEmpty()) { if (CacheUtil.dataMap.containsKey(sid)) { // 是否在有效期内 Date expireDate = CacheUtil.dataExpireMap.get(sid); if (expireDate != null && expireDate.compareTo(new Date()) > 0) { url = (String) CacheUtil.get(sid); // 文件是否存在 File existFile = new File(fileDir + url ); if (!existFile.exists()) { modelMap.put( "msg", "该文件已不存在~" ); return "error.html"; } } else { modelMap.put( "msg", "分享文件已过期" ); return "error.html"; } } else { modelMap.put( "msg", "无效的sid" ); return "error.html"; } } return getFile( url, download, response ); } /** * 查看/下载分享的源文件 * * @param sid 分享sid * @param response * @return */ @GetMapping("/share/file") public String shareFile(@RequestParam(value = "sid", required = true) String sid, @RequestParam(value = "d", required = true) int d, HttpServletResponse response, ModelMap modelMap) { return returnShareFileOrSm( sid, d == 1 ? true : false, modelMap, response ); } /** * 分享源文件的缩略图 * * @param sid 分享sid * @param response * @return */ @GetMapping("/share/file/sm") public String shareFileSm(@RequestParam(value = "sid", required = true) String sid, HttpServletResponse response, ModelMap modelMap) { return returnShareFileOrSm( sid, false, modelMap, response ); } /** * 查看缩略图 * * @param p 文件全名 * @param response * @return */ @Login @GetMapping("/file/sm") public String fileSm(@RequestParam("p") String p, HttpServletResponse response) { return getFile( p,false, response ); } /** * 输出文件流 * * @param file * @param download 是否下载 * @param response */ private void outputFile(String file, boolean download, HttpServletResponse response) { // 判断文件是否存在 File inFile = new File(file); // 文件不存在 if (!inFile.exists()) { PrintWriter writer = null; try { response.setContentType("text/html;charset=UTF-8"); writer = response.getWriter(); writer.write("
FMS Server
"); writer.flush(); } catch (IOException e) { e.printStackTrace(); } return; } // 获取文件类型 String contentType = null; try { contentType = new Tika().detect(inFile); } catch (IOException e) { e.printStackTrace(); } // 图片、文本文件,则在线查看 log.info("文件类型:" + contentType); if (FileTypeUtil.canOnlinePreview(contentType) && !download) { response.setContentType(contentType); response.setCharacterEncoding("UTF-8"); } else { // 其他文件,强制下载 response.setContentType( "application/force-download" ); String newName; try { newName = URLEncoder.encode( inFile.getName(), "utf-8" ); } catch (UnsupportedEncodingException e) { e.printStackTrace(); newName = inFile.getName(); } response.setHeader("Content-Disposition", "attachment;fileName=" + newName ); } // 输出文件流 OutputStream os = null; FileInputStream is = null; try { is = new FileInputStream(inFile); os = response.getOutputStream(); byte[] bytes = new byte[1024]; int len; while ((len = is.read(bytes)) != -1) { os.write(bytes, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 获取文件类型 * * @param suffix * @param contentType * @return */ private String getFileType(String suffix, String contentType) { String type; if (FileTypeEnum.PPT.getName().equalsIgnoreCase(suffix) || FileTypeEnum.PPTX.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.PPT.getName(); } else if (FileTypeEnum.DOC.getName().equalsIgnoreCase(suffix) || FileTypeEnum.DOCX.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.DOC.getName(); } else if (FileTypeEnum.XLS.getName().equalsIgnoreCase(suffix) || FileTypeEnum.XLSX.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.XLS.getName(); } else if (FileTypeEnum.PDF.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.PDF.getName(); } else if (FileTypeEnum.HTML.getName().equalsIgnoreCase(suffix) || FileTypeEnum.HTM.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.HTM.getName(); } else if (FileTypeEnum.TXT.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.TXT.getName(); } else if (FileTypeEnum.SWF.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.FLASH.getName(); } else if (FileTypeEnum.ZIP.getName().equalsIgnoreCase(suffix) || FileTypeEnum.RAR.getName().equalsIgnoreCase(suffix) || FileTypeEnum.SEVENZ.getName().equalsIgnoreCase(suffix)) { type = FileTypeEnum.ZIP.getName(); } else if (contentType != null && contentType.startsWith(FileTypeEnum.AUDIO.getName() + SLASH)) { type = FileTypeEnum.MP3.getName(); } else if (contentType != null && contentType.startsWith(FileTypeEnum.VIDEO.getName() + SLASH)) { type = FileTypeEnum.MP4.getName(); } else { type = FileTypeEnum.FILE.getName(); } return type; } /** * 获取全部文件 * * @param dir * @param accept * @param exts * @return Map */ @Login @ResponseBody @RequestMapping("/api/list") public Map list(String dir, String accept, String exts) { String[] mExts = null; if (exts != null && !exts.trim().isEmpty()) { mExts = exts.split(","); } if (fileDir == null) { fileDir = SLASH; } if (!fileDir.endsWith(SLASH)) { fileDir += SLASH; } Map