文件管理(上传与预览)
上传文件到本地指定目录(windows环境),实现视频浏览器播放,linux环境实现文件读取配置代理服务器即可。
Controller层
@RestController
@RequestMapping("/sysFiles")
@Api(tags = "文件管理")
public class SysFilesController {
@Resource
private SysFilesService sysFilesService;
@ApiOperation(value = "上传")
@PostMapping("/upload")
public UEditorResultVO add(
@RequestParam(required = false) String action,
@RequestParam(value = "file") MultipartFile file) {
return sysFilesService.saveFile(file,fileParameters);
}
@ApiOperation(value = "文件预览")
@GetMapping("/preview/{id}")
public void preview(@PathVariable String id, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
sysFilesService.preview(id, req, res);
}
@ApiOperation(value = "文件下载")
@GetMapping("/download/{id}")
public void download(@PathVariable String id, HttpServletRequest req, HttpServletResponse res) {
sysFilesService.download(id, req, res);
}
}
Service层
@Service("sysFilesService")
public class SysFilesServiceImpl extends ServiceImpl<SysFilesMapper, SysFilesEntity> implements SysFilesService {
@Resource
private FileUploadProperties fileUploadProperties;
@Autowired
private NonStaticResourceHttpRequestConfig nonStaticResourceHttpRequestConfig;
@Override
public UEditorResultVO saveFile(MultipartFile file, FileParameters fileParameters) {
if (ObjectUtil.isEmpty(file)) {
throw new BusinessException(BaseResponseCode.UPLOAD_EMPTY);
}
//存储文件夹
String createTime = DateUtils.format(new Date(), DateUtils.DATEPATTERN);
String newPath = fileUploadProperties.getPath() + createTime + File.separator;
File uploadDirectory = new File(newPath);
if (uploadDirectory.exists()) {
if (!uploadDirectory.isDirectory()) {
uploadDirectory.delete();
}
} else {
uploadDirectory.mkdir();
}
try {
String fileName = file.getOriginalFilename();
//获取文件大小
int fileSize = (int) file.getSize();
//获取文件的后缀名
String suffixName = fileName.substring(fileName.lastIndexOf(".")+1);
//id与filename保持一直,删除文件
String fileNameNew = UUID.randomUUID().toString().replace("-", "") + getFileType(fileName);
String newFilePathName = newPath + fileNameNew;
// String url = fileUploadProperties.getUrl() + "/" + createTime + "/" + fileNameNew;
//创建输出文件对象
File outFile = new File(newFilePathName);
//拷贝文件到输出文件对象
FileUtils.copyInputStreamToFile(file.getInputStream(), outFile);
//保存文件记录
SysFilesEntity sysFilesEntity = new SysFilesEntity();
//sysFilesEntity 自己的文件对象
this.save(sysFilesEntity);
// String hostAddress = InetAddress.getLocalHost().getHostAddress();
String hostAddress = getLocalHostExactAddress().getHostAddress();
// String url = fileUploadProperties.getUrl() + "/preview" + "/" + sysFilesEntity.getId();
String url = "http://" + hostAddress + fileUploadProperties.getUrl() + sysFilesEntity.getId();
sysFilesEntity.setUrl(url);
this.updateById(sysFilesEntity);
UEditorResultVO uEditorResult = new UEditorResultVO();
uEditorResult.setState("SUCCESS");
uEditorResult.setUrl(url);
uEditorResult.setId(sysFilesEntity.getId());
uEditorResult.setTitle(fileNameNew);
uEditorResult.setOriginal(fileName);
return uEditorResult;
} catch (Exception e) {
throw new BusinessException(BaseResponseCode.UPLOAD_FAILED);
}
}
public static InetAddress getLocalHostExactAddress() {
try {
InetAddress candidateAddress = null;
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface iface = networkInterfaces.nextElement();
// 该网卡接口下的ip会有多个,也需要一个个的遍历,找到自己所需要的
for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
InetAddress inetAddr = inetAddrs.nextElement();
// 排除loopback回环类型地址(不管是IPv4还是IPv6 只要是回环地址都会返回true)
if (!inetAddr.isLoopbackAddress()) {
if (inetAddr.isSiteLocalAddress()) {
// 如果是site-local地址,就是它了 就是我们要找的
// ~~~~~~~~~~~~~绝大部分情况下都会在此处返回你的ip地址值~~~~~~~~~~~~~
return inetAddr;
}
// 若不是site-local地址 那就记录下该地址当作候选
if (candidateAddress == null) {
candidateAddress = inetAddr;
}
}
}
}
// 如果出去loopback回环地之外无其它地址了,那就回退到原始方案吧
return candidateAddress == null ? InetAddress.getLocalHost() : candidateAddress;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取请求ip地址
* @throws Exception Exception
*/
private String getRemoteIP() throws Exception {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = "";
if (request.getHeader("x-forwarded-for") == null) {
ip = request.getRemoteAddr();
}else{
ip = request.getHeader("x-forwarded-for");
}
return ip;
}
/**
* 校验文件类型的正则
**/
public static String fileCheck(String suffixName) {
String reg1 = "(mp4|flv|avi|mov|rm|rmvb|wmv|hevc)";
Pattern pattern1 = Pattern.compile(reg1);
boolean flag1 = pattern1.matcher(suffixName.toLowerCase()).find();
if (flag1){
return "视频";
}
String reg = "(jpg|png|tiff|webp|heif|gif|bmp)";
Pattern pattern = Pattern.compile(reg);
boolean flag = pattern.matcher(suffixName.toLowerCase()).find();
if (flag){
return "图片";
}
return "文件";
}
@Override
public void preview(String id, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
if (id != null) {
SysFilesEntity entity = this.getById(id);
String path = entity.getFilePath();
res.setContentLength(entity.getFileSize());
//保存文件路径
Path filePath = Paths.get(path);
//获取文件的类型,比如是MP4这样
File file = new File(path);
String mimeType = Files.probeContentType(filePath);
if (StrUtil.isNotEmpty(mimeType)) {
//判断类型,根据不同的类型文件来处理对应的数据
res.setContentType(mimeType);
res.addHeader("Content-Length", "" + file.length());
}
//转换流部分
req.setAttribute(NonStaticResourceHttpRequestConfig.ATTR_FILE, filePath);
nonStaticResourceHttpRequestConfig.handleRequest(req, res);
}
}
@Override
public void download(String id, HttpServletRequest req, HttpServletResponse res) {
if (id != null) {
SysFilesEntity entity = this.getById(id);
String path = entity.getFilePath();
setDownloadContent(entity.getFileName(), req, res);
// 重要,需要设置此值,否则下载后打开文件会提示文件需要修复
res.setContentLength(entity.getFileSize());
File file = new File(path);
if (file.exists()) {
byte[] buffer = new byte[1024];
//输出流
OutputStream os;
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);) {
os = res.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
/**
* 客户端下载文件上response header的设置。
*
* @param fileName 文件名
* @param request 请求
* @param response 响应
*/
private void setDownloadContent(String fileName, HttpServletRequest request, HttpServletResponse response) {
String agent = request.getHeader("User-Agent");
try {
if (null != agent && agent.toUpperCase().indexOf("MSIE") > 0) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
}
} catch (UnsupportedEncodingException e1) {
}
response.setContentType("application/x-msdownload;");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
}
@Override
public void removeByIdsAndFiles(List<String> ids) {
List<SysFilesEntity> list = this.listByIds(ids);
list.forEach(entity -> {
//如果之前的文件存在,删除
File file = new File(entity.getFilePath());
if (file.exists()) {
file.delete();
}
});
this.removeByIds(ids);
}
/**
* 获取文件后缀名
*
* @param fileName 文件名
* @return 后缀名
*/
private String getFileType(String fileName) {
if (fileName != null && fileName.contains(".")) {
return fileName.substring(fileName.lastIndexOf("."));
}
return "";
}
}
相关配置类
@Component
@ConfigurationProperties(prefix = "file")
@EnableConfigurationProperties(FileUploadProperties.class)
public class FileUploadProperties {
private String path;
private String url;
private String accessUrl;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
//set accessUrl
if (StringUtils.isEmpty(url)) {
this.accessUrl = null;
}
this.accessUrl = url.substring(url.lastIndexOf("/")) + "/**";
System.out.println("accessUrl=" + accessUrl);
}
public String getAccessUrl() {
return accessUrl;
}
}
@Component
public class NonStaticResourceHttpRequestConfig extends ResourceHttpRequestHandler {
public final static String ATTR_FILE = "NON-STATIC-FILE";
@Override
protected Resource getResource(HttpServletRequest request) {
final Path filePath = (Path) request.getAttribute(ATTR_FILE);
return new FileSystemResource(filePath);
}
}
上传返回结果
这样一个简单的文件上传就做好啦!