本文实例为大家分享了Axios+Spring Boot实现文件上传和下载的具体代码,供大家参考,具体内容如下
1.所用技术
前端:Vue + Axios
后端:Springboot + SpringMVC
2.单文件上传
后端代码
只需要使用MultipartFile类配合RequestBody注解即可
@PostMapping("your/path") public ResultData courseCoverUpload(@RequestBody MultipartFile file){ ? ? /** ? ? your service ? ? */ }
前端代码
Axios上传需要设置头部,使用FormData封装文件对象
//file为文件对象 function upload(file){ ? ? //请求头设置 ? ? const header={"Content-type":"multipart/form-data"} ? ? let formData=new FormData(); ? ? //用file作为key没问题,其他没试过 ? ? formData.append("file",file); ? ??? ?//这里request封装过,也可以直接使用axios.post() ?? ?request.post(`path`,formData,{headers:header}).then(res=>{ ? ? ? ? //your serivce ? ? }) }
如若使用element-ui的upload组件,可以选择自定义上传方法(好处是可以再请求头中加入token)
<el-upload ? ? ? class="upload-demo" ? ? ? :auto-upload="false" ? ? ? action ? ? ? :http-request="uploadFile" ? ? ? ref="upload" ? ? ? > ? ? ? ? ? <el-button type="text">点击上传</el-button> </el-upload>
上述uploadFile正是上传时的回调函数,使用方法如下
function uploadFile(param){ ?? ?//param中的file才是真正的文件体,用于传入axios上传方法的参数 ?? ?upload( param.file ) },
3.文件上传的同时传输Json数据
后端代码
将@RequestBody换成==@RequestPart==注解,并再注解中加入接收时的识别key即可同时接受文件和其他Json参数
@PostMapping("up") public ResultData uploadTest( ?? ?@RequestPart("file") MultipartFile file,? ?? ?@RequestPart("other") Map<String,String> props ?? ?){ ?? ?return ResultData.success().data("file_size",file.getSize()).data("others",props); }
前端代码
function ?uploadFile(file_body,other_json){ ? ? //头信息不变 ? ? const header={"Content-type":"multipart/form-data"} ?? ?//依旧用FormData作数据封装 ? ? let form_data=new FormData(); ? ? //此处的key要与后端统一,这里都使用file ? ? form_data.append("file",file_body) ? ? //再封装其他参数时需要使用Blob,[]不要错,type一定要加 ?? ?form_data.append( "other",new Blob([JSON.stringify(other_json)],{type:"application/json"})) ?? ?//这里request封装过,也可以直接使用axios.post() ? ? request.post(url,form_data,{headers: header}).then(rs=>{ ? ? ? console.log(rs); ? ? }) }
4.文件下载
使用axios下载文件最恶心之处就在于前后端请求头还有解析格式要匹配,否则就会出现跨域或者文件流出错等问题。
后端代码
和返回json数据不同,返回文件流需要使用HttpServletResponse类的输出流将文件流逐一打印出去,这里选择用过滤器处理请求,也可以使用Controller
编写接收前端请求的过滤器
public class FileFilter implements Filter , InputOutputUtil { ? ? @Override ? ? public void doFilter(ServletRequest servletRequest, ? ? ? ? ? ? ? ? ? ? ? ? ?ServletResponse servletResponse, ? ? ? ? ? ? ? ? ? ? ? ? ?FilterChain filterChain) throws IOException, ServletException { ? ? ? ? /** 本次后端默认前端使用Get请求进行下载,如若get需要传递参数可以用getParameter方式获取 ?? ? ? ? ? ?HttpServletRequest request = (HttpServletRequest) servletRequest; ? ? ?? ? ? ?System.out.println(request.getParameter("a")); ? ? ? ? */ ? ? ? ? //获取文件输出流,这里是读取本地的 ? ? ? ? File ?f= new File("file_path"); ? ? ? ? InputStream inpurStream = new FileInputStream(file); ? ? ? ? /** 如果文件资源在其他服务器上(比如阿里云的OSS),可以用以下代码获取文件流 ? ? ? ? URLConnection urlConn = new URL("URL_PATH").openConnection(); ? ? ? ? urlConn.connect(); ? ? ? ? InputStream inputStream = urlConn.getInputStream(); ? ? ? ? */ ? ? ? ?? ? ? ? ? //输出方法,放在了自己编写的InputOutputUtil中 ? ? ? ? this.writeFile(servletResponse,"security_key.jpg",inputStream); ? ? } }
辅助输出的接口
public interface InputOutputUtil { ? ? //输出文件时用 ? ? default void writeFile(ServletResponse servletResponse, ? ? ? ? ? ? ? ? ? ? ? ? ? ?String fileName,InputStream inputStream) throws IOException { ? ? ? ? HttpServletResponse response = (HttpServletResponse) servletResponse; ? ? ? ? //设置返回的头信息 ? ? ? ? response.setContentType("application/octet-stream"); ? ? ? ? response.setCharacterEncoding("UTF-8"); ? ? ? ? response.addHeader("Content-disposition", "attachment;filename=\""+fileName+"\""); ? ? ? ?? ? ? ? ? //跨域处理 ? ? ? ? response.setHeader("Access-Control-Expose-Headers","Content-Disposition"); ? ? ? ? response.setHeader("Access-Control-Allow-Origin","*"); ? ? ? ? response.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE"); ? ? ? ? response.setHeader("Access-Control-Allow-Headers","*"); ? ? ? ? response.setHeader("Access-Control-Max-Age","false"); ? ? ? ? response.setHeader("Access-Control-Allow-Credentials","10"); ? ? ? ?? ? ? ? ? //获取输出流 ? ? ? ? ServletOutputStream outputStream=response.getOutputStream(); ? ? ? ? //将文件流逐一放入输出流中打印给前端 ? ? ? ? byte[] bs1=new byte[1024]; ? ? ? ? int length; ? ? ? ? while((length=inputStream.read(bs1))!=-1){ ? ? ? ? ? ? outputStream.write(bs1,0,length); ? ? ? ? } ? ? ? ? //关流操作 ? ? ? ? outputStream.close(); ? ? ? ? inputStream.close(); ? ? } }
前端代码
使用axios的get方法发起请求
function downloadFile(url,param=null){ ? ? //设置头信息 ? ? let config = {responseType:'blob'} ? ? //如若前端有参数就加入一下 ? ? if (param!=null) config["params"]=param ? ? //带着头信息和请求参数发起请求 ? ? request.get(url,config).then(res=>{ ? ? ? ? //如若成功了,开始拆箱 ? ? ? ? //获取filename,这里使用的是正则表达式,关联 辅助输出接口 的第9行 ? ? ? ? let file_name=res.headers["content-disposition"].match(/filename=\"(\S*)\"/)[1] ? ? ? ? //data中装的是文件体,需要使用Blob流可以下载 ? ? ? ? let blob = new Blob([res.data]) ? ? ? ?? ? ? ? ? //网上最常用的下载方法 ? ? ? ? let downloadElement = document.createElement('a') ? ? ? ? let href = window.URL.createObjectURL(blob); //创建下载的链接 ? ? ? ? downloadElement.href = href; ? ? ? ? downloadElement.download = file_name; //下载后文件名 ? ? ? ? document.body.appendChild(downloadElement); ? ? ? ? downloadElement.click(); //点击下载 ? ? ? ? document.body.removeChild(downloadElement); //下载完成移除元素 ? ? ? ? window.URL.revokeObjectURL(href); //释放blob对象 ? ? }) }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
查看更多关于Axios+Spring Boot实现文件上传和下载的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did122196