前言
最近参与了一个小项目,主要负责的是文件的跨服务器传送,其中包含按要求对文件进行压缩后传送,实现的时候使用的是Restful接口,实现的过程中遇到了很多关于文件File的操作,感觉实现的时候有思路知道该如何如何实现这个功能,但是具体的代码实现还是得百度搜索,想着之后也会常用不如总结一下,后续遇到相关操作继续更新~
常用操作
一、MultipartFile转File
SpringBoot中通常前端上传文件到后端,对应接口的文件参数类型为MultipartFile,后端获取到这个MultipartFile对象之后需要将其转为File对象,然后存到本地/文件服务器上。
try {
// 将文件存入指定目录中(需要确保文件确实存在)
File sendFile = new File(path);
// file为MultipartFile类型
file.transferTo(sendFile);
} catch (IOException e) {
e.printStackTrace();
}
二、File转MultipartFile
// 需要确保path对应的文件存在
File file = new File(path);
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile =new MockMultipartFile(“file”, file.getName(), “text/plain”, IOUtils.toByteArray(input));
拓展一个小知识点:
使用RestTemplate发送文件的方法,将文件使用FileSystemResource转为文件流进行发送,注意需要设置请求头的类型为MULTIPART_FORM_DATA,设置成整个格式主要是因为接收方的参数类型也一般为MultipartFile
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
//设置提交方式都是表单提交
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//设置表单信息
MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("file", new FileSystemResource(new File(filePath)));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
restTemplate.postForEntity(
"http://xxx:xx/xxxxx",requestEntity, Object.class);
注意一个特别小的点:
File对象获取文件名使用getName()方法获取
MultipartFile对象获取文件名需要使用getOriginalFilename()获取
三、创建File
上述两种操作都涉及文件的创建,普通的File file = new File(path);一定要明确这个只是创建了一个文件对象,根据file对象的相关方法对file进行操作,但是方法执行的前提是这个file真实存在,这条语句并不能在文件不存在的时候自动创建,所以需要我们抽取一个方法创建文件。
考虑到有时候文件的目录即文件夹不存在,所以一般会先判断文件夹是否存在,如果不存在的话mkdirs()方法创建文件夹,之后再判断file文件是否存在,如果不存在则创建(注意会特意给这个file对象赋予写权限,以防无权限而报错)
public static File createNewFile(String path, String fileName) throws IOException {
File fileDir = new File(path);
if (!fileDir.exists() && !fileDir.isDirectory()) {
// fileDir的mkdir()方法只是创建最近一层的目录,如果根目录中有不存在的会创建最近一级目录失败。例如directory/test/路径,mkdir()方法是创建test目录,如果directory不存在,test会创建失败
fileDir.mkdirs();
}
File file = new File(path + fileName);
if (file.exists()) {
file.delete();
}
// 文件设置可写
file.setWritable(true);
file.createNewFile();
return file;
}
这里拓展说一下一般项目中不会固定文件的路径,因为Windows和Linux的文件路径表达方式不同,所以一般会使用项目的绝对路径。
/**
* 文件路径分隔符 /
*/
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
/**
* 文件存储路径
*/
public static final String FILE_DIRECTORY = System.getProperty("user.dir") + FILE_SEPARATOR + "Directory";
要么是在项目配置文件resouces/application.yml中写文件存储的相对路径,文件夹置入项目目录下,然后使用@Value或者properties对象加载获取
// application.yml配置path的存储路径
path: D:\test\test.txt
// 调用
@Value("${path}")
private String path;
// 通过properties对象获取
public class testProperties {
Properties p = new Properties();
InputStream in = testProperties.class.getClassLoader().getResourceAsStream("application.yml");
p.load(in);
String name = p.getProperty("className");
}
四、判断File/MultipartFile是否为图片
判断是否为图片的主要思路就是摘取文件名,看是否满足以png、jpeg、jpg、gif结尾,使用正则表达式匹配即可
/**
* 常用图片格式 ^表示正则表达式开始,$表示正则表达式结束,这个正则表达式是 .叠加上jpeg/jpg/png/gif中的任意一个
*/
public static final String REG_IMG_FORMAT = "^.+(.JPEG|.jpeg|.JPG|.jpg|.PNG|.png|.GIF|.gif)$";
/**
* 判断MultipartFile对象是否为图片
* @param file
* @return
*/
public static boolean isImage(MultipartFile file) {
Matcher matcher = Pattern.compile(Const.REG_IMG_FORMAT).matcher(file.getOriginalFilename());
return matcher.find();
}
/**
* 判断File对象是否为图片
* @param file
* @return
*/
public static boolean isImage(File file) {
Matcher matcher = Pattern.compile(Const.REG_IMG_FORMAT).matcher(file.getName());
return matcher.find();
}
五、获取文件后缀
用户上传的图片名千奇百怪,为了避免不同用户上传相同文件名的文件而导致前一个文件被覆盖,通常会对用户上传至后端的文件名进行改造。本人常用的方式是使用随机生成的UUID,然后使用空字符串替换掉其中的"-",然后叠加原本文件的后缀,保证文件的类型。那么如何获取文件后缀是一个问题,常用的方法是利用后缀的特征(以"."结尾)字符串的lastIndexOf(".")方法获取到最后一个"."在这个字符串中的索引值,然后使用substring方法截取从这个索引值开始一直到字符串末尾的值。
/**
* 获取文件后缀 .+后缀
* @param file
* @return
*/
public static String getSuffix(MultipartFile file){
// 获