学堂 学堂 学堂公众号手机端

基于vue框架怎样实现文件上传下载,具体代码是什么

lewis 1年前 (2024-03-30) 阅读数 6 #技术
这篇文章给大家分享的是“基于vue框架怎样实现文件上传下载,具体代码是什么”,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下吧。


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对象
  })
}

关于“基于vue框架怎样实现文件上传下载,具体代码是什么”就介绍到这了,如果大家觉得不错可以参考了解看看,如果想要了解更多,欢迎关注博信,小编每天都会为大家更新不同的知识。
版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门