Springboot搭建文件服务器

您所在的位置:网站首页 springboot将文件传到服务器上 Springboot搭建文件服务器

Springboot搭建文件服务器

#Springboot搭建文件服务器| 来源: 网络整理| 查看: 265

笔者最近遇到了一个需求,需要搭建一个文件服务器,用于上传文件(.txt格式等)和图片(.jpg格式等)。

下面演示怎么上传txt文件和上传头像(.jpg),如有需要可自行修改后缀名进行拓展。

准备工作:

配置文件以及配置类:主要配置不同类型的文件路径,比如上传头像,可以放到 avatar目录,上传不同类型的文件方便区分,并获取其指定的上传路径。

配置文件application.yml:

# 项目相关配置 file-service: # 文件路径 profile: D:/profile/

这里我配置了默认文件路径在D:/profile/,这里要注意:自定义配置文件属性规范名称应为kebab-case(’ - '分隔),小写字母数字字符,并且必须以字母开头。也就是说 如果写 fileService 或 FileService都是错的。

配置类WebConfig.java

import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 读取项目相关配置 * * @author 健康搬砖人 */ @Component @ConfigurationProperties(prefix = "file-service") public class WebConfig { /** * 上传路径 */ private static String profile; public static String getProfile() { return profile; } public void setProfile(String profile) { WebConfig.profile = profile; } // 获取上传头像路径 public static String getAvatarPath() { return profile + "avatar/"; } // 获取下载路径 public static String getDownloadPath() { return profile + "download/"; } // 获取上传路径 public static String getUploadPath() { return profile + "upload/"; } }

依赖文件:

Pom.xml需要用到如下的依赖:

org.apache.commons commons-lang3 commons-io commons-io 2.5

org.apache.commons这个是常用工具类,用于文件分类,后面我会写一个DateUtils,目的用于生成上传或下载的日期文件夹,比如上传个头像,目录可能是这样的

D:/profile/avatar/2019/05/20/d025ba6f937f59999a021989a12a1aab.jpg

其中的2019/05/20就是根据你上传或下载的日期而定。

日期处理类:

import org.apache.commons.lang3.time.DateFormatUtils; import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 时间工具类 * * @author 健康搬砖人 */ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { public static String YYYY = "yyyy"; public static String YYYY_MM = "yyyy-MM"; public static String YYYY_MM_DD = "yyyy-MM-dd"; public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; /** * 获取当前Date型日期 * * @return Date() 当前日期 */ public static Date getNowDate() { return new Date(); } /** * 获取当前日期, 默认格式为yyyy-MM-dd * * @return String */ public static String getDate() { return dateTimeNow(YYYY_MM_DD); } public static final String getTime() { return dateTimeNow(YYYY_MM_DD_HH_MM_SS); } public static final String dateTimeNow() { return dateTimeNow(YYYYMMDDHHMMSS); } public static final String dateTimeNow(final String format) { return parseDateToStr(format, new Date()); } public static final String dateTime(final Date date) { return parseDateToStr(YYYY_MM_DD, date); } public static final String parseDateToStr(final String format, final Date date) { return new SimpleDateFormat(format).format(date); } public static final Date dateTime(final String format, final String ts) { try { return new SimpleDateFormat(format).parse(ts); } catch (ParseException e) { throw new RuntimeException(e); } } /** * 日期路径 即年/月/日 如2018/08/08 */ public static final String datePath() { Date now = new Date(); return DateFormatUtils.format(now, "yyyy/MM/dd"); } /** * 日期路径 即年/月/日 如20180808 */ public static final String dateTime() { Date now = new Date(); return DateFormatUtils.format(now, "yyyyMMdd"); } /** * 日期型字符串转化为日期 格式 */ public static Date parseDate(Object str) { if (str == null) { return null; } try { return parseDate(str.toString(), parsePatterns); } catch (ParseException e) { return null; } } /** * 获取服务器启动时间 */ public static Date getServerStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); return new Date(time); } /** * 计算两个时间差 */ public static String getDatePoor(Date endDate, Date nowDate) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; // long ns = 1000; // 获得两个时间的毫秒时间差异 long diff = endDate.getTime() - nowDate.getTime(); // 计算差多少天 long day = diff / nd; // 计算差多少小时 long hour = diff % nd / nh; // 计算差多少分钟 long min = diff % nd % nh / nm; // 计算差多少秒//输出结果 // long sec = diff % nd % nh % nm / ns; return day + "天" + hour + "小时" + min + "分钟"; } }

MD5加密类:用于对文件名进行hash加密,防止上传的文件名相同。

package com.warren.springboot.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.MessageDigest; /** * Md5加密方法 * * @author 健康搬砖人 */ public class Md5Utils { private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); private static byte[] md5(String s) { MessageDigest algorithm; try { algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(s.getBytes("UTF-8")); byte[] messageDigest = algorithm.digest(); return messageDigest; } catch (Exception e) { log.error("MD5 Error...", e); } return null; } private static final String toHex(byte hash[]) { if (hash == null) { return null; } StringBuffer buf = new StringBuffer(hash.length * 2); int i; for (i = 0; i buf.append("0"); } buf.append(Long.toString(hash[i] & 0xff, 16)); } return buf.toString(); } public static String hash(String s) { try { return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8"); } catch (Exception e) { log.error("not supported charset...{}", e); return s; } } }

文件上传工具类:

import com.warren.springboot.config.WebConfig; //这个是导入上面的WebConfig.java配置文件 import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; /** * 文件上传工具类 * * @author 健康搬砖人 */ public class FileUploadUtils { /** * 默认大小 50M */ public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; /** * 默认的文件名最大长度 100 */ public static final int DEFAULT_FILE_NAME_LENGTH = 100; /** * 默认上传的地址 */ private static String defaultBaseDir = WebConfig.getProfile(); /** * 默认文件类型jpg */ public static final String IMAGE_JPG_EXTENSION = ".jpg"; private static int counter = 0; public static void setDefaultBaseDir(String defaultBaseDir) { FileUploadUtils.defaultBaseDir = defaultBaseDir; } public static String getDefaultBaseDir() { return defaultBaseDir; } /** * 根据文件路径上传 * * @param baseDir 相对应用的基目录 * @param file 上传的文件 * @return 文件名称 * @throws IOException */ public static final String uploadPicture(String baseDir, MultipartFile file) throws IOException { try { return upload(baseDir, file, FileUploadUtils.IMAGE_JPG_EXTENSION); } catch (Exception e) { throw new IOException(e.getMessage(), e); } } /** * 根据文件路径上传 * * @param baseDir 相对应用的基目录 * @param file 上传的文件 * @return 文件名称 * @throws IOException */ public static final String uploadText(String baseDir, MultipartFile file) throws IOException { try { return upload(baseDir, file, ".txt"); } catch (Exception e) { throw new IOException(e.getMessage(), e); } } /** * 文件上传 * * @param baseDir 相对应用的基目录 * @param file 上传的文件 * @param extension 上传文件类型 * @return 返回上传成功的文件名 * @throws IOException 比如读写文件出错时 */ public static final String upload(String baseDir, MultipartFile file, String extension) throws IOException{ int fileNamelength = file.getOriginalFilename().length(); if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) { // 此处可进行异常处理throws System.out.println("文件名长度超出限定长度"); } assertAllowed(file); String fileName = extractFilename(file, extension); File desc = getAbsoluteFile(baseDir, baseDir + fileName); file.transferTo(desc); return fileName; } public static final String extractFilename(MultipartFile file, String extension) { String filename = file.getOriginalFilename(); filename = DateUtils.datePath() + "/" + encodingFilename(filename) + extension; return filename; } private static final File getAbsoluteFile(String uploadDir, String filename) throws IOException { File desc = new File(File.separator + filename); if (!desc.getParentFile().exists()) { desc.getParentFile().mkdirs(); } if (!desc.exists()) { desc.createNewFile(); } return desc; } /** * 编码文件名 */ private static final String encodingFilename(String filename) { filename = filename.replace("_", " "); filename = Md5Utils.hash(filename + System.nanoTime() + counter++); return filename; } /** * 文件大小校验 * * @param file 上传的文件 */ public static final void assertAllowed(MultipartFile file) {//throws FileSizeLimitExceededException { long size = file.getSize(); if (size > DEFAULT_MAX_SIZE) { // 此处可进行异常处理throws System.out.println("文件大小超出最大限定大小"); } } }

准备工作就到这里结束了,下面直接就放大招了。

项目实战 一、文件上传 /** * 保存文件 * * @param file 文件 * @return 结果 */ @PostMapping("/updateFile") @ResponseBody public Object updateFile(@RequestParam("file") MultipartFile file) { try { if (!file.isEmpty()) { String fileName = FileUploadUtils.uploadText(WebConfig.getUploadPath(), file); System.out.println("fileName:" + fileName); // TODO: 此处可以根据项目需求的业务进行操作,例如将fileName保存到数据库 } return "success"; } catch (Exception e) { return "error"; } } 二、头像/图片上传

图片上传和文件上传类似。

/** * 保存头像 * * @param file 头像文件 * @return 结果 */ @PostMapping("/updateAvatar") @ResponseBody public Object updateAvatar(@RequestParam("avatarfile") MultipartFile file) { try { if (!file.isEmpty()) { String avatar = FileUploadUtils.uploadPicture(WebConfig.getAvatarPath(), file); System.out.println("avatar:" + avatar); // TODO: 此处可以根据项目需求的业务进行操作,例如此处操作的是头像,可以将头像url保存到数据库,用户登录后,获取相应的url获取头像图片。 } return "success"; } catch (Exception e) { return "error"; } } 三、文件下载

这里文件下载的业务分为几种。

①直接查看图片,类似业务:查看图片/查看头像

/** * 查看文件 * * @param url 图片url * @param response 请求响应 */ @RequestMapping(value = "/noLogin/readImageFile",method =RequestMethod.GET) @ResponseBody public void getUrlFile(String url, HttpServletResponse response) { // 这里的url,我为了测试,直接就写静态的。 url = "D:/profile/avatar/2019/05/20/d025ba6f937f59999a021989a12a1aab.jpg"; File file = new File(url); // 后缀名 String suffixName = url.substring(url.lastIndexOf(".")); //判断文件是否存在如果不存在就返回默认图片或者进行异常处理 if (!(file.exists() && file.canRead())) { // file = new File("xxx/xxx.jpg"); System.out.println("文件不存在"); } FileInputStream inputStream = null; try { inputStream = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; inputStream.close(); response.setContentType("image/png;charset=utf-8"); OutputStream stream = response.getOutputStream(); stream.write(data); stream.flush(); stream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

效果如下:

在这里插入图片描述

②将文件内容(.txt)封装到一个String里

@RequestMapping(value = "/noLogin/readFileToString",method = RequestMethod.GET) @ResponseBody public String getUrlFile(String url, HttpServletRequest request, HttpServletResponse response) { // url = "D:/profile/upload/2019/05/20/01017f12b88d9f4e79dc38060e3883da.txt"; // 通过url创建文件 File file = new File(url); // 后缀名 String suffixName = url.substring(url.lastIndexOf(".")); //判断文件是否存在如果不存在就进行异常处理 if (!(file.exists() && file.canRead())) { System.out.println("文件不存在"); } FileInputStream inputStream = null; String content = ""; try { inputStream = new FileInputStream(file); inputStream.close(); // 使用FileUtils将File内容以UTF-8的编码写到String里 content = FileUtils.readFileToString(file, "UTF-8"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; }

③文件下载

/** * 下载文件 * * @param url 文件url * @param response 请求响应 */ @RequestMapping(value = "/noLogin/downloadFile",method =RequestMethod.GET) @ResponseBody public void getUrlDownload(String url, HttpServletResponse response) { url = "D:/profile/avatar/2019/05/20/d025ba6f937f59999a021989a12a1aab.jpg"; File file = new File(url); // 后缀名 String suffixName = url.substring(url.lastIndexOf(".")); //判断文件是否存在如果不存在就进行异常处理 if (!(file.exists() && file.canRead())) { System.out.println("文件不存在"); } FileInputStream inputStream = null; BufferedInputStream bufferedInputStream = null; try { inputStream = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; int length = inputStream.read(data); inputStream.close(); response.setContentType("application/force-download"); //通过设置头信息给文件命名,也即是,在前端,文件流被接受完还原成原文件的时候会以你传递的文件名来命名 response.addHeader("Content-Disposition",String.format("attachment; filename=\"%s\"", file.getName())); OutputStream stream = response.getOutputStream(); stream.write(data); stream.flush(); stream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

效果如下:

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3