国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 關(guān)于SpringBoot大文件RestTemplate下載解決方案

關(guān)于SpringBoot大文件RestTemplate下載解決方案

2022-02-27 15:11人無名,則可專心練劍 Java教程

這篇文章主要介紹了SpringBoot大文件RestTemplate下載解決方案,最近結(jié)合網(wǎng)上案例及自己總結(jié),寫了一個分片下載tuling/fileServer項目,需要的朋友可以參考下

近期基于項目上使用到的RestTemplate下載文件流,遇到1G以上的大文件,下載需要3-4分鐘,因為調(diào)用API接口沒有做分片與多線程, 文件流全部采用同步方式加載,性能很慢。最近結(jié)合網(wǎng)上案例及自己總結(jié),寫了一個分片下載tuling/fileServer項目: 1.包含同步下載文件流在瀏覽器加載輸出相關(guān)代碼; 2.包含分片多線程下載分片文件及合并文件相關(guān)代碼;

另外在DownloadThread項目中使用代碼完成了一個遠(yuǎn)程RestUrl請求去獲取一個遠(yuǎn)端資源大文件進(jìn)行多線程分片下載 到本地的一個案例,可以下載一些諸如.mp4/.avi等視頻類大文件。相關(guān)代碼也一并打包上傳。

同步下載,支持分片下載Range主要代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@Controller
public class DownLoadController {
    private static final String UTF8 = "UTF-8";
    @RequestMapping("/download")
    public void downLoadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        File file = new File("D:\\DevTools\\ideaIU-2021.1.3.exe");
        response.setCharacterEncoding(UTF8);
        InputStream is = null;
        OutputStream os = null;
        try {
            // 分片下載 Range表示方式 bytes=100-1000  100-
            long fSize = file.length();
            response.setContentType("application/x-download");
            String fileName = URLEncoder.encode(file.getName(), UTF8);
            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 numberRange = request.getHeader("Range").replaceAll("bytes=", "");
                String[] strRange = numberRange.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(numberRange.replaceAll("-", "").trim());
                }
            }
            long rangeLength = last - pos + 1;
            String contentRange = new StringBuffer("bytes").append(pos).append("-").append(last).append("/").append(fSize).toString();
            response.setHeader("Content-Range", contentRange);
            response.setHeader("Content-Length", String.valueOf(rangeLength));
 
            os = new BufferedOutputStream(response.getOutputStream());
            is = new BufferedInputStream(new FileInputStream(file));
            is.skip(pos);
            byte[] buffer = new byte[1024];
            int length = 0;
            while (sum < rangeLength) {
                int readLength = (int) (rangeLength - sum);
                length = is.read(buffer, 0, (rangeLength - sum) <= buffer.length ? readLength : buffer.length);
                sum += length;
                os.write(buffer,0, length);
            }
            System.out.println("下載完成");
        }finally {
            if (is != null){
                is.close();
            }
            if (os != null){
                os.close();
            }
        }
    }
}

多線程分片下載分片文件,下載完成之后合并分片主要代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
@RestController
public class DownloadClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(DownloadClient.class);
    private final static long PER_PAGE = 1024L * 1024L * 50L;
    private final static String DOWN_PATH = "F:\\fileItem";
    ExecutorService taskExecutor = Executors.newFixedThreadPool(10);
 
    @RequestMapping("/downloadFile")
    public String downloadFile() {
        // 探測下載
        FileInfo fileInfo = download(0, 10, -1, null);
        if (fileInfo != null) {
            long pages =  fileInfo.fSize / PER_PAGE;
            for (long i = 0; i <= pages; i++) {
                Future<FileInfo> future = taskExecutor.submit(new DownloadThread(i * PER_PAGE, (i + 1) * PER_PAGE - 1, i, fileInfo.fName));
                if (!future.isCancelled()) {
                    try {
                        fileInfo = future.get();
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }
            return System.getProperty("user.home") + "\\Downloads\\" + fileInfo.fName;
        }
        return null;
    }
 
    class FileInfo {
        long fSize;
        String fName;
 
        public FileInfo(long fSize, String fName) {
            this.fSize = fSize;
            this.fName = fName;
        }
    }
 
    /**
     * 根據(jù)開始位置/結(jié)束位置
     * 分片下載文件,臨時存儲文件分片
     * 文件大小=結(jié)束位置-開始位置
     *
     * @return
     */
    private FileInfo download(long start, long end, long page, String fName) {
        File dir = new File(DOWN_PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        // 斷點下載
        File file = new File(DOWN_PATH, page + "-" + fName);
        if (file.exists() && page != -1 && file.length() == PER_PAGE) {
            return null;
        }
        try {
            HttpClient client = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet("http://127.0.0.1:8080/download");
            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.parseLong(fSize) > 0) {
                // 開始合并文件
                mergeFile(fName, page);
            }
 
            return new FileInfo(Long.parseLong(fSize), fName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    private void mergeFile(String fName, long page) {
        File file = new File(DOWN_PATH, fName);
        try {
            BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
            for (long i = 0; i <= page; i++) {
                File tempFile = new File(DOWN_PATH, i + "-" + fName);
                while (!file.exists() || (i != page && tempFile.length() < PER_PAGE)) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                byte[] bytes = FileUtils.readFileToByteArray(tempFile);
                os.write(bytes);
                os.flush();
                tempFile.delete();
            }
            File testFile = new File(DOWN_PATH, -1 + "-null");
            testFile.delete();
            os.flush();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 獲取遠(yuǎn)程文件尺寸
     */
    private long getRemoteFileSize(String remoteFileUrl) throws IOException {
        long fileSize = 0;
        HttpURLConnection httpConnection = (HttpURLConnection) new URL(remoteFileUrl).openConnection();
        //使用HEAD方法
        httpConnection.setRequestMethod("HEAD");
        int responseCode = httpConnection.getResponseCode();
        if (responseCode >= 400) {
            LOGGER.debug("Web服務(wù)器響應(yīng)錯誤!");
            return 0;
        }
        String sHeader;
        for (int i = 1;; i++) {
            sHeader = httpConnection.getHeaderFieldKey(i);
            if (sHeader != null && sHeader.equals("Content-Length")) {
                LOGGER.debug("文件大小ContentLength:" + httpConnection.getContentLength());
                fileSize = Long.parseLong(httpConnection.getHeaderField(sHeader));
                break;
            }
        }
        return fileSize;
    }
 
    class DownloadThread implements Callable<FileInfo> {
        long start;
        long end;
        long page;
        String fName;
 
        public DownloadThread(long start, long end, long page, String fName) {
            this.start = start;
            this.end = end;
            this.page = page;
            this.fName = fName;
        }
 
        @Override
        public FileInfo call() {
            return download(start, end, page, fName);
        }
    }
}

代碼都在本地親測(已修復(fù)Bug)可用,目前比較欠缺的是沒有實現(xiàn)在分片下載時對應(yīng)瀏覽器進(jìn)行下載展示,需要暫存在本地磁盤目錄。 目前將代碼開源,希望能有更好解決方案的Coder Fork支持!也歡迎Star捧場。

博文參考了圖靈學(xué)院相關(guān)的分片下載案例教程,并修改了部分代碼實現(xiàn):

WebUploader--基于SpringBoot搭建,Java文件上傳下載高階實戰(zhàn)

本文代碼已上傳至GitHub:

BurstDownload

到此這篇關(guān)于SpringBoot大文件RestTemplate下載解決方案的文章就介紹到這了,更多相關(guān)SpringBoot RestTemplate下載內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.cnblogs.com/yif0118/p/15456666.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日比视频网站 | 色欧美片视频在线观看 | 亚洲特黄一级 | 欧美日韩国产精品一区二区 | 欧美日韩一区二区三区免费视频 | 欧美视频精品 | 欧美黄色小视频 | 久久1区| 久久久999国产 | 色在线播放 | 色接久久 | 日韩一区精品 | 奇米亚洲午夜久久精品 | 日韩在线一区二区 | 精品一区二区三区免费视频 | 免费黄色电影在线观看 | 中文字幕亚洲欧美日韩在线不卡 | 欧美在线视频网站 | 欧美视频在线免费 | 一区视频在线 | 在线干| 午夜激情在线播放 | 日韩视频中文字幕 | 成人国产精品免费观看 | 国产亚洲精品美女久久久久久久久久 | 九九在线精品视频 | 国产精品久久久久久久午夜片 | 国产精品毛片一区视频播不卡 | 亚洲男女视频在线观看 | 欧美精品一区在线观看 | 毛片在线免费 | 伊人无码高清 | 欧美日韩国产精品一区二区 | 日本久久久久久久久久久久 | www.五月婷 | 中国久久久 | 伊人欧美在线 | 日本精品在线观看视频 | 在线观看一区二区三区四区 | 久久久精品国产99久久精品芒果 | av成人在线观看 |