Springboot文件下载方式(直接下载)

2023-12-24 18:53:25
package com.example.demo.controller;

import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@RequestMapping("/upload3")
@RestController
public class uploadController {
    //定义分片有多大
    private  final  static  long PER_PAGE=1024l*1024l*50l;
    //设置分片存储的临时目录
    private  final  static  String DOWN_PATH="C:\\Users\\Lenovo\\Desktop\\lianxi";
    //下载文件的地址
    private  final  static String url="http://localhost:8080/upload3/downLoad/";
    //文件存放的位置
    private  final  static String pathfile=System.getProperty("user.dir")+"\\static\\upload\\";
    ExecutorService pool= Executors.newFixedThreadPool(10);
    //文件大小文件名字
    // 探测 获取文件信息
    // 多线程分片下载

    //最后一个分片下载完 始合并
    @RequestMapping("/downLoadFile/{filename}")
    public void downLoadFile(@PathVariable("filename") String filename) throws IOException, InterruptedException {
        FileInfo fileInfo = download(0, 10, -1, null,filename);
        if (fileInfo!=null) {
            long pages= fileInfo.fSize/PER_PAGE;

            for(long i=0;i<=pages;i++){
                pool.submit(new DownLoad(i* PER_PAGE,(i+1)*PER_PAGE-1,i,fileInfo.fName,filename));
           }
        }


    }
    class DownLoad implements Runnable{
        long start;
        long end;
        long page;
        String fName;
        String fileName;

        public DownLoad(long start, long end, long page, String fName, String fileName) {
            this.start = start;
            this.end = end;
            this.page = page;
            this.fName = fName;
            this.fileName = fileName;
        }

        @Override
        public void run() {
            try {
                download(start,end,page,fName,fileName);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    class  FileInfo{
        long fSize;
        String fName;

        public FileInfo(long fSize, String fName) {
            this.fSize = fSize;
            this.fName = fName;
        }
    }
    //结束的位置开始的位置=分片大小
    private FileInfo download(long start,long end,long page,String fName,String fileName) throws IOException, InterruptedException {
        File file = new File(DOWN_PATH, page + "-" + fName);
        if (file.exists() && page!=-1 &&file.length()==PER_PAGE){
            return  null;
        }
        HttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url+fileName);
        httpGet.setHeader("Range","bytes="+start+"-"+end);
        HttpResponse response = client.execute(httpGet);
        String fSize = response.getFirstHeader("fSize").getValue();
        fName= URLDecoder.decode(response.getFirstHeader("fName").getValue(),"utf-8");

        HttpEntity entity = response.getEntity();
        InputStream is = entity.getContent();
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int ch;
        while ((ch=is.read(buffer))!=-1){
            fos.write(buffer,0,ch);
        }
        is.close();
        fos.flush();
        fos.close();
        if (end -Long.valueOf(fSize)>0){
            mergeFile(fName,page);
        }
        return new FileInfo(Long.valueOf(fSize),fName);
    }

    private void mergeFile(String fName, long page) throws IOException, InterruptedException {
        File file=new File(DOWN_PATH,fName);
        BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
        for (int i = 0; i <=page; i++) {
            File temFile = new File(DOWN_PATH, i + "-" + fName);
            while (!file.exists()||(i!=page && temFile.length()<PER_PAGE)){
                Thread.sleep(100);
            }
            byte[] bytes=  FileUtils.readFileToByteArray(temFile);
            os.write(bytes);
            os.flush();
            temFile.delete();
        }
        File file1=new File(DOWN_PATH,-1+"-null");
        file1.delete();
        os.flush();
        os.close();
    }

    @RequestMapping("/downLoad/{filename}")
    public void downLoadFile(@PathVariable("filename") String filename, HttpServletResponse response, HttpServletRequest request) throws IOException {
        //文件存在的路径
        String path = pathfile+filename;
        //String path="D:\\java 录屏\\20231216_183319.mp4";
        File file = new File(path);
        if(!file.exists()){
            return;
        }
        //设置编码
        response.setCharacterEncoding("utf-8");
        //输入输出对象
        InputStream is=null;
        OutputStream os=null;
        //关闭流try
        try{
            //分片下载
            //获取文件长度
            long fSize=file.length();
            //设置头
            response.setContentType("application/x-download");
            String fileName= URLEncoder.encode(file.getName(),"utf-8");
            //让前端弹出对话框下到哪里
            response.addHeader("Content-Disposition","attachment;filename="+filename);
            //告诉前端支持分片下载
            response.setHeader("Accept-Range","bytes");
            //设置下载文件的大小
            response.setHeader("fSize",String.valueOf(fSize));
            //告诉前端文件名字
            response.setHeader("fName", fileName);

            long pos=0,last=fSize-1,sum=0;
            if (null !=request.getHeader("Range")){
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                String numRange= request.getHeader("Range").replaceAll("bytes=","");
                String[] strRange = numRange.split("-");
                if(strRange.length==2){
                    pos=Long.parseLong(strRange[0].trim());
                    last=Long.parseLong(strRange[1].trim());
                    //如果结束字节超出文件大小
                    if(last>fSize-1){
                        last=fSize-1;
                    }
                } else {
                    pos=Long.parseLong(numRange.replaceAll("-","").trim());
                }
            }
            long rangeLenght = last - pos + 1;
            String contentRange=new StringBuffer("bytes ").append(pos).append("-").append(last).append("/").append(fSize).toString();
            response.setHeader("Content-Range",contentRange);
            response.setHeader("Cotent-Lenght",String.valueOf(rangeLenght));

            os=new BufferedOutputStream(response.getOutputStream());
            is=new BufferedInputStream(new FileInputStream(file));
            is.skip(pos);
            byte[] buffer=new byte[1024];
            int lenght=0;
            while (sum<rangeLenght){
                lenght=is.read(buffer,0,((rangeLenght-sum)<=buffer.length?((int)(rangeLenght-sum)):buffer.length));
                sum=sum+lenght;
                os.write(buffer,0,lenght);
            }
        }finally {
            if (is!=null){
                is.close();
            }
            if (os!=null){
                os.close();
            }
        }

    }

}

导入依赖

<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

访问路径:localhost:8080/upload3/downLoadFile/下载的东西

传递的参数:下载的文件名

文章来源:https://blog.csdn.net/weixin_62907807/article/details/135180474
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。