补充SpringMVC的文件上传以及文件下载

SpringMVC之文件上传以及文件下载

页面:

<form action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="fName">
<input type="file" name="myFile">
<input type="submit" value="提交">
</form>

文件上传必备属性enctype="multipart/form-data"

controller:

/**
* 文件上传
*/
@RequestMapping("/upload")
@ResponseBody
public Map<String, Object> upload(String fName, MultipartFile myFile) {
//定义一个返回值
HashMap<String, Object> map = new HashMap();
try {
//1.获取文件输入流
System.out.println(fName);
System.out.println(myFile);
InputStream is = myFile.getInputStream();
System.out.println(is);
String url = "F:\\Typora文件\\upload\\";
File file = new File(url + myFile.getOriginalFilename());
//文件输出流
OutputStream os = new FileOutputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
//文件边读边写
while ((len = is.read(bytes)) != -1) {
os.write(bytes);
}
//文件关闭流
os.close();
is.close();
//如果成功保存文件信息就返回一个成功的msg
map.put("msg", "保存成功");
} catch (IOException e) {
e.printStackTrace();
//如果出现异常情况就返回一个失败的msg
map.put("msg", "保存失败");
}
return map;
}

文件上传思路:

在服务端上传文件,是以文件流的形式进行的,所以得先获取文件的输入流(is),有了输入流就会有个输出流(os),输出流针对的参数那就是一个文件,所以我们得先new File文件。由于文件上传到客户端在磁盘中进行保存,而我们PC电脑既充当客户端,也充当服务端,所以我们可以在桌面创建一个文件夹,复制它的绝对路径url,然而我们上面new Flie文件的参数需要确定上传的文件的全路径,我们上传的所有形式的文件的全路径都基于我们桌面新建文件的url地址+上传文件的文件名+后缀,所以在new Flie对象中的参数为url+myflie.getOriginalFilename,后面的myflie.getOriginalFilename()方法可以直接获取到上传文件的文件名+后缀。最后我们对输出的文件进行边读边写的操作,因为不知道我们上传的文件需要进行几次读写操作所以使用while循环,调用is.read()方法读取一个文件容器的字节大小,每读一次就会返回一个长度值,只有长度不为-1就会一直读下去知道长度为-1,然后读一次就执行一次写文件的操作os.write(定义的文件容器的字节大小)

 

文件下载过程

我们在页面上指定下载资源<a href="/download?filename=dsb.jpg">资源下载</a>后,还需要再Controller中编写我们将要进行的操作:

 /**
    * 文件下载
    */
   @RequestMapping("/download")
   @ResponseBody
   public Map<String, Object> download(String filename,HttpServletResponse response) {
       System.out.println(filename);
       //定义一个返回值
       HashMap<String, Object> map = new HashMap();
//       指定提供资源的磁盘的目录
       String dir="F:\\Typora文件\\SpringBoot\\img\\";
//       拼接该文件地址-判定该文件是否存在
       File file = new File(dir + filename);
//进行判断是否存在
       if (file.exists()){
//           存在--读取文件--响应文件--关闭流
           try {
//           创建输入流对象--读取磁盘文件
               InputStream inputStream = new FileInputStream(file);
//             创建一个获取文件输出流对象 可以看成FileOutputStream
               ServletOutputStream outputStream = response.getOutputStream();
//               指定文件的名称
               response.setHeader("Content-Disposition","filename="+filename);
//               文件类型
               response.setHeader("Content-Type","application/jpeg");
//读取过程
               byte []bytes=new byte[2048];
               int len=0;
               while ((len=inputStream.read(bytes))!=-1){
                   outputStream.write(bytes,0,len);
              }
//               关闭流
               outputStream.close();
               inputStream.close();
          } catch (FileNotFoundException e) {
               e.printStackTrace();
          } catch (IOException e) {
               e.printStackTrace();
          }
      }else {
//           如果文件不存--响应改文件不存在
           map.put("msg", "文件下载失败--文件不存在");
      }
       return map;
  }

 

而在链接中我们给了定了资源为dsb.jpg,我们在Controller中获取到后,还需要进行指定这个图片资源的位置在哪里。

//            创建输入流对象--读取磁盘文件
               InputStream inputStream = new FileInputStream(file);

在指定完后,我们还需要进行判断文件资源是否存在。

//        指定提供资源的磁盘的目录
       String dir="F:\\Typora文件\\SpringBoot\\img\\";
//       拼接该文件地址-判定该文件是否存在
       File file = new File(dir + filename);
//进行判断是否存在
       if (file.exists()){
        ....
      }

在判断完成后若是存在,需要去读取磁盘中的文件,创建一个文件输出流。

//             创建一个获取文件输出流对象  可以看成FileOutputStream
               ServletOutputStream outputStream = response.getOutputStream();

同时我们还需要返回响应头的,让浏览器可以返回下载框,并给其设置下载文件的名称:

//                指定文件的名称
               response.setHeader("Content-Disposition","filename="+filename);
//               文件类型
               response.setHeader("Content-Type","application/jpeg");

然后在读取下载资源并写入文件

//读取过程
               byte []bytes=new byte[2048];
               int len=0;
               while ((len=inputStream.read(bytes))!=-1){
                   outputStream.write(bytes,0,len);
              }

 

遇到的问题

  1. 使用restful风格无法获取到我们我们所需的资源。 在路径上我们无法去读取<a href="/download/dsb.jpg">资源下载</a>到dsb.jpg的文件,会报一个406的错误。

  2. 获取资源类型的格式。

//                文件类型
               response.setHeader("Content-Type","application/jpeg");

这里jpg格式的一般来说是要在找到相应的格式去进行下载,找到一个资源是:image/jpeg 使用这个格式。

posted @   孤巷一人i  阅读(262)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示