当我们在做项目时难免都要上传附件,这时我们会用到市面上开源的文件服务器,例如FastDFS,ServU,HDFS等文件服务器,我想我可不可以做一个简易版本的小型文件服务器系统呢?
文件服务器作为服务端,自然要接收客户端发送来的文件并将文件写入本地磁盘,然后做一些处理可以预览附件,那么这一句话就够用了,下面开始动手写一个简易的文件服务器。
写这个服务器没有用到数据库,全都是文件流的操作,仅此而已!
写对外开放的为客户端上传附件的接口,参数为MultipartFile对象,客户端只需要直接将文件MultipartFile参数传过来即可。 其中文件上传到了Tomcat/webapps/中的一个文件夹,同时Tomcat要开启状态,因为拼接上域名和文件路径以及文件名就可以直接下载了。
@Controller @RequestMapping("/rest") public class CreateFileController { //硬盘文件地址(存储文件地址) // private static final String dirPath="D:\\suibian\\test\\"; private static final String dirPath="/usr/local/share/apache-tomcat-8.5.40/webapps/files/"; //Tomcat域名,拼接上文件名可直接下载 private static final String tomcatUrl="https://www.tiger2.cn/files/"; //客户端向本服务端上传文件的开放接口 @PostMapping("createFile") @ResponseBody public Map<String, Object> createFile(MultipartFile uploadFile, String uploader) { String message = ""; boolean success = true; //构建新的文件名并进行存储,存储到云服务的文件夹中 String originalFilename = uploadFile.getOriginalFilename(); String suffix=originalFilename.substring(originalFilename.lastIndexOf(".")); long time=new Date().getTime(); String newFileName=originalFilename.substring(0,originalFilename.lastIndexOf("."))+String.valueOf(time)+suffix; try { //FileUtils.copyInputStreamToFile是commons-io包下的方法,可以直接将输入流转为一个新的文件(前提是指定好路径和要生成的文件名) FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), new File(dirPath + newFileName)); } catch (Exception e) { message = e.getMessage(); success = false; } Map<String, Object> result = new HashMap<>(); result.put("message", message); result.put("success", success); result.put("newFileName",newFileName); //返回一个新的文件名 result.put("downLoadUrl",tomcatUrl+newFileName);//返回文件下载地址 return result; } @Autowired LoginController loginController; //根据文件名创建在线预览地址 @GetMapping(value = "createPreviewUrl", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public String createPreviewUrl(String fileName){ String previewUrl = loginController.createPreviewUrl(fileName); return previewUrl; } }上面生成附件在线预览地址的方法不用细看了,这里使用了永中云转换服务,只需要把下载地址作为参数给它们,它们会直接给你生成预览地址,不过免费的局限性很大。
点我到永中云转换服务
获取到要下载的文件File对象,得到输入流之后,将输入流写入到响应请求response的输出流中,在浏览器端进行下载。
//根据文件名称下载文件输出到浏览器 @RequestMapping("/download") @ResponseBody public void download(String fileName, HttpServletResponse response) throws Exception{ //windows分隔符是\\ Linux分隔符是/ String fileName1=dirPath+"/"+fileName; //获取要下载的文件输入流 FileInputStream is=new FileInputStream(new File(fileName1)); //设置content-disposition响应头控制浏览器以下载的形式打开文件 response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")); OutputStream out = response.getOutputStream(); byte[] bytes=new byte[1024]; int len; while ((len=is.read(bytes))>0){ out.write(bytes,0,len); } //关闭输入流 is.close(); }FileUtils.copyInputStreamToFile是commons-io包下的方法,可以直接将输入流转为一个新的文件(前提是指定好路径和要生成的文件名)
//服务器本身上传图片到服务器本地硬盘 @RequestMapping("/upload") public String upload(MultipartFile file,Model model) throws Exception{ boolean checkFileSize = checkFileSize(file, 5, "M"); if(true){ String originalFilename = file.getOriginalFilename(); long time=new Date().getTime(); String suffix=originalFilename.substring(originalFilename.lastIndexOf(".")); String name=originalFilename.substring(0,originalFilename.lastIndexOf(".")); FileUtils.copyInputStreamToFile(file.getInputStream(),new File(dirPath+"/"+name+String.valueOf(time)+suffix)); model.addAttribute("msg","The File Was Uploaded Successlly!"); return "forward:index"; }else{ model.addAttribute("msg","Sorry, The File Was Uploaded Error!The File Size Should Not Exceed 5MB!"); return "forward:index"; } }参数分别是文件,数字,单位(B,K,M,G)
public static boolean checkFileSize( MultipartFile multipartFile, int size, String unit) { long len = multipartFile.getSize();//上传文件的大小, 单位为字节. //准备接收换算后文件大小的容器 double fileSize = 0; if ("B".equals(unit.toUpperCase())) { fileSize = (double) len; } else if ("K".equals(unit.toUpperCase())) { fileSize = (double) len / 1024; } else if ("M".equals(unit.toUpperCase())) { fileSize = (double) len / 1048576; } else if ("G".equals(unit.toUpperCase())) { fileSize = (double) len / 1073741824; } //如果上传文件大于限定的容量 if (fileSize > size) { return false; } return true; }准备一个表单,提交附件
<form action="/upload/tiger2" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="uploadFile" /> <input type="submit" value="上传" /> </form>使用RestTemplate把文件从客户端发送至服务端的接收文件的接口。
@RequestMapping("/tiger2") @ResponseBody public Map uploadFile(MultipartFile uploadFile){ FileServerManager fileServerManager=new FileServerManager(); Map result = fileServerManager.uploadFileToTiger2Server(uploadFile); return result; } public Map uploadFileToTiger2Server(MultipartFile uploadFile) { RestTemplate restTemplate = new RestTemplate(); MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap(); HttpHeaders header = new HttpHeaders(); header.setContentType(MediaType.MULTIPART_FORM_DATA); HttpHeaders fileHeader = new HttpHeaders(); fileHeader.setContentType(MediaType.parseMediaType(uploadFile.getContentType())); fileHeader.setContentDispositionFormData("uploadFile", uploadFile.getOriginalFilename()); Map result = null; try { HttpEntity<ByteArrayResource> fileEntity = new HttpEntity(new ByteArrayResource(uploadFile.getBytes()), fileHeader); multiValueMap.add("uploadFile", fileEntity); String url = "http://fileserver.tiger2.cn/rest/createFile"; HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(multiValueMap, header); ResponseEntity<Map> postForEntity = restTemplate.postForEntity(url, httpEntity, Map.class, new Object[0]); result = (Map)postForEntity.getBody(); } catch (Exception var11) { ; } return result; }都是RestTemplate的基本操作,这个就不说了吧!
完美谢幕!