目录
总体介绍
文件上传
介绍
文件上传的前端需求
文件上传的前端代码
文件上传的后端需求
文件上传的后端代码
文件下载
介绍
前端需求
前端代码
后端需求
后端代码
总体介绍
文件的上传和下载功能,是项目开发过程中比较常见的业务需求,我们在客户端被展现的视觉效果通过如下:在项目前端页面的提示下将本地文件加入到浏览器的具体位置,之后浏览器直接将这个图片回显了,具体效果如下:
但是在我们视觉效果下的上传文件并非单一的文件上传过程:而是由文件的上传和下载两部分组成,即文件从客户端本地上传到服务器和由服务器把文件在浏览器进行回显(下载到服务器中),接下来我们对两个过程进行具体介绍
文件上传
介绍
文件上传,也称为上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程.文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能.
文件上传的前端需求
但是在实际的开发过程中,前端页面有关这一部分的设计通常是使用组件进行封装,例如使用element-ui在完成功能实现的基础上实现了对上传组件页面设计的优化。(底层仍然是使用post表单的方式进行发送请求)
如下:
文件上传的前端代码
具体实现上传功能的element-ui的代码如下:
<div class="addBrand-container" id="food-add-app"><div class="container"><el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></div></div>
文件上传的后端需求
服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:
- commons-fileupload
- commons-io
Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller的方法中声明一个MultipartFile类型的参数即可接收上传的文件,例如:
关于对于文件上传的后端实现逻辑,一般是如下的实现思路:
1.首先使用MultipartFile类的形参接收客户端传来的文件,我们需要注意的是:MultipartFile类对象接收到文件之后,会对文件进行一个暂存,生成一个临时文件,当我们结束此次传输过程之后,无论是否对文件进行了转存,这个临时文件都会消失,
2.因此我们下一步的操作就是对这个暂时文件进行转存,因为文件转存过程中必然会涉及到文件名的问题,如果使用原有文件的文件名可能会存在文件名重复的问题,因此在原来的基础上生成一个新的随机文件名,以新的文件名进行转存,
2.最后一定要记得返回我们新生成的那个文件名,因为upload只是将文件上传到服务器了,后面还涉及一次将文件在浏览器上进行回显的工作,需要使用到这个文件名
我们给出文件上传的后端代码实现:
文件上传的后端代码
我们通过使用@Value注解从配置文件中读取文件保存路径:
@Value("${reggie.path}")private String path;
reggie:path: D:\img\
@PostMapping("/upload")public R<String>upload(MultipartFile file){log.info(file.toString());//获取原始文件名,提取JPGString originalFilename = file.getOriginalFilename();String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//生成随机文件名String random=UUID.randomUUID().toString();//获取新名称String fileName=random+suffix;//创建新名称File file1 = new File(path);if(!file1.exists()){file1.mkdirs();}//进行转存try {log.info("文件路径为"+path+fileName);file.transferTo(new File(path+fileName));} catch (IOException e) {throw new RuntimeException(e);}return R.success(fileName);}
notes:关于MultipartFile类对象名:这个对象名必须与前端传来的对象名保持一致,也就是说是前后端的交互是以对象名进行匹配的,如果对象名不一致,传到后端的MultipartFile文件对象就是一个空对象了,具体演示如下:
文件下载
介绍
文件下载,也被称为download,是指将文件从服务器传到本地计算机的过程
通过浏览器进行文件下载,通常有两种表现形式:
- 以附件形式进行下载,弹出保存对话框,将文件保存到指定的磁盘目录
- 直接在浏览器中打开
通过浏览器进行文件下载,本质上就是服务端将文件以流的形式协会到浏览器的过程
前端需求
想要实现完整图片回显的功能,下载之前必须要完成上传功能,并且要拿到需要回显文件的文件名,所以前端的需求就是根据upload响应返回的文件名向服务端发送新的请求获取文件信息,以此进行照片信息的回显,代码实例和具体的请求url如下
代码示例:
url展示:我们可以发现,download的url中包含了具体图片的文件名
前端代码
具体的前端代码如下:
methods: {handleAvatarSuccess (response, file, fileList) {this.imageUrl = `/common/download?name=${response.data}`},beforeUpload (file) {if(file){const suffix = file.name.split('.')[1]const size = file.size / 1024 / 1024 < 2if(['png','jpeg','jpg'].indexOf(suffix) < 0){this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')this.$refs.upload.clearFiles()return false}if(!size){this.$message.error('上传文件大小不能超过 2MB!')return false}return file}}}
后端需求
后端接收到前端传来的文件名,根据文件路径和文件名创建FileInputStream对象,利用response对象创建ServletOutputStream对象,从FileInputStream文件中读取数据并通过数组写入ServletOutputStream对象,最后记得一定要关闭流资源
后端代码
后端代码如下:
@GetMapping("/download")public void downLoad(String name, HttpServletResponse response){//输入流,通过提供指定位置去读取数据try {FileInputStream fileInputStream = new FileInputStream(new File(path + name));//输出流,通过读取到的数据输出到浏览器中ServletOutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg");//将数据通过byte字符数组进行读取int len=0;byte[]bytes=new byte[1024];while((len=fileInputStream.read(bytes))!=-1){outputStream.write(bytes,0,len);//刷新outputStream.flush();}fileInputStream.close();outputStream.close();} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}