SpringBoot文件上传和下载的基础处理方式.

467 阅读3分钟

文件上传

一.前端文件上传基础代码:

<form 
  method="post" enctype="multipart/form-data" 
  action="http://localhost:8080/file/upload"
>
  <input name="myFile" type="file">
  <input type="submit" value="提交">
</form>

以下部分为固定内容,不可改变.

1.method="post" 采用post方式提交数据

2.enctype="multipart/form-data" 采用multipart格式上传文件(二进制格式,传输效率最高)

3.type="file" 使用input的file控件上传文件

二.Controller中使用MultipartFile类型,即可接收上到上传的文件.

@PostMapping("/file/upload")
public R<String> upload(MultipartFile file) throws UnsupportedEncodingException {
    String fileName = this.fileUpload.run(file);
    return R.success(fileName);
}

重点: MultipartFile接收的变量名必须与前端上传控件的name属性同名.

如:<input name="myFile" type="file">VSpublic R<String> upload(MultipartFile file) ,此处myFile==myFile;

PS:MultipartFile的底层是对spring-web对Apache中的两个组件commons-fileuploadcommons-io;

三.专门创建一个类用于处理上传后的文件.将之保存到本地硬盘中.

public class FileUpload {
    /**
     * 上傳文件
     * @param myFile 文件
     */
    public String run(MultipartFile myFile) {
        //确保我们保存文件的目录存在
        this.guaranteeFileDirectory();
        //随机生成的文件名
        String randomFileName = this.generateRandomFileName(myFile);
        try {
            //myFile:在本次请求中,它是以临时文件的方式存在于tomcat中,当本次请求结束的时候,该临时文件将被删除.
            //将临时文件转存到别的位置,避免被删除.
            myFile.transferTo(new File("D:\\uploadfile\\" + randomFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return randomFileName;
    }
    //确保目录存在:判断当前目录是否存在,若不存在,则生成一个目录
    private void guaranteeFileDirectory() {
        File dir = new File("D:\\uploadfile\\");
        if (!dir.exists()) {
            //目录不存在,需要创建
            dir.mkdir();
        }
    }

    //使用UUID随机生成一个文件名.
    private String generateRandomFileName(MultipartFile myFile) {
        //原始文件名
        String originalFilename = myFile.getOriginalFilename();
        //取得文件后缀
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        //在部分真实场景中,文件表中还需要保存文件的类型
        //String fileType = myFile.getContentType();
        //使用UUID重新生成新的文件名,防止文件名重复造成文件覆盖
        String randomFileName = UUID.randomUUID().toString() + suffix;
        return randomFileName;
    }
}

四.在Controller中将保存的文件名返回给前端 image.png 至此,上传功能已完成.

文件下载

一.前端下载文件表现形式.

1.以附件形式下载,弹出对话框,选择文件保存的位置;

2.直接在浏览器中打开浏览(如:<img src="http://localhost:8080/download/avatar.png" />);

两种的本质都是服务端将文件以【流】的形式写回浏览器.

二.Controller中使用HttpServletResponse的方式将值写回给前端(区别于其他场景直接返回JSON格式数据).

/**
 * 文件下载
 *
 * @param fileName     文件名
 * @param response
 */
@GetMapping("/download/{fileName}")
public void downloadFile(@PathVariable String fileName, HttpServletResponse response) {
    this.fileDownload.run(fileName, response);
}

三.专门建一个类处理文件的下载.

public class FileDownload {
    /**
     * 下載文件
     *
     * @param name 文件名
     * @param response
     */
    public void run(String fileName, HttpServletResponse response) {
        try {
            //指定向浏览器传输的文件类型.
            //在实际开发中,在上传的时候,会同时存入文件的类型,在下载的时候,会返回文件的类型
//            response.setContentType("image/jpeg");
            //从【本地】读取文件,生成流对象
            FileInputStream fileInputStream = new FileInputStream(new File("D:\\uploadfile\\" + fileName));
            //使用 服务端输出流API(ServletOutputStream) 将流输出到浏览器
            ServletOutputStream outputStream = response.getOutputStream();
            //使用输入流将文件置入bytes数组,然后再通过response中的输入流将文件返回给前端
            int length = 0;
            byte[] bytes = new byte[1024];
            while (length != -1) {
                //从输入流中读取(取出)多个字节数据,如到输入流末尾则返回-1
                length = fileInputStream.read(bytes);
//                System.out.println("打印出读取到的字节长度length:---->"+length);
                //使用API将流写入待发送缓存区
                outputStream.write(bytes,0,length);
                //手动将缓存中的流数据发送至浏览器(不手动发送,满了也会自动发送,手动发送更稳定)
                outputStream.flush();
            }
            //关闭资源
            outputStream.close();
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

四.前端只要传入的文件名,就可以直接通过路径的【GET】请求,取得文件数据.当然,也可以将路径写在<img src="路径"/>. image.png

完.