Skip to content

Commit aceceef

Browse files
committed
添加对应115文件流读取的支持
1 parent 2b90c97 commit aceceef

9 files changed

Lines changed: 163 additions & 17 deletions

File tree

CHANGELOG.MD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
更新日志文档,版本顺序从新到旧,最新版本在最前(上)面。
44

5+
# 1.0.7
6+
7+
- 添加对应115文件流读取的支持
8+
59
# 1.0.6
610

711
- 修复问题

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ ext {
1414
springContext = '6.0.3'
1515
pf4j = '3.8.0'
1616
lombok = '1.18.24'
17-
libFile = 'lib/api-1.0.4.jar'
17+
libFile = 'lib/api-1.0.5.jar'
1818
}
1919

2020

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
group=run.ikaros.plugin
22
description=A pan115 plugin for ikaros.
3-
version=1.0.6
3+
version=1.0.7

lib/api-1.0.5-sources.jar

78 KB
Binary file not shown.

lib/api-1.0.5.jar

211 KB
Binary file not shown.

src/main/java/run/ikaros/plugin/pan115/Pan115AttachmentDriverFetcher.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,18 @@
22

33
import lombok.extern.slf4j.Slf4j;
44
import org.pf4j.Extension;
5-
import org.springframework.stereotype.Component;
5+
import org.springframework.core.io.buffer.DataBuffer;
66
import org.springframework.util.Assert;
77
import reactor.core.publisher.Flux;
88
import reactor.core.publisher.Mono;
9-
import reactor.core.scheduler.Schedulers;
109
import run.ikaros.api.core.attachment.Attachment;
1110
import run.ikaros.api.core.attachment.AttachmentDriver;
1211
import run.ikaros.api.core.attachment.AttachmentDriverFetcher;
1312
import run.ikaros.api.core.attachment.AttachmentDriverOperate;
1413
import run.ikaros.api.infra.utils.StringUtils;
15-
import run.ikaros.api.wrap.PagingWrap;
1614
import run.ikaros.api.store.enums.AttachmentDriverType;
1715
import run.ikaros.api.store.enums.AttachmentType;
1816
import run.ikaros.plugin.pan115.model.Pan115Attachment;
19-
import run.ikaros.plugin.pan115.model.Pan115Folder;
2017
import run.ikaros.plugin.pan115.model.Pan115Path;
2118
import run.ikaros.plugin.pan115.repository.Pan115Repository;
2219
import run.ikaros.plugin.pan115.utils.FileUtils;
@@ -165,6 +162,16 @@ public Mono<String> parseDownloadUrl(Attachment attachment) {
165162
}
166163
}
167164

165+
@Override
166+
public Flux<DataBuffer> getSteam(Attachment attachment) {
167+
Assert.notNull(attachment, "'attachment' must not null.");
168+
AttachmentType type = attachment.getType();
169+
if (AttachmentType.Driver_Directory.equals(type)) return Flux.empty();
170+
Long driverId = attachment.getDriverId();
171+
Mono<AttachmentDriver> checkoutMono = checkoutToken(driverId);
172+
return checkoutMono.flatMapMany(driver -> pan115Repository.openUFileSteam(attachment.getUrl()));
173+
}
174+
168175
private void applyPan115Token(AttachmentDriver driver) {
169176
Assert.notNull(driver, "'driver' must not null.");
170177
pan115Repository.refreshToken(driver);

src/main/java/run/ikaros/plugin/pan115/repository/DefaultPan115Repository.java

Lines changed: 141 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@
33
import com.fasterxml.jackson.core.type.TypeReference;
44
import lombok.extern.slf4j.Slf4j;
55
import org.apache.commons.lang3.StringUtils;
6+
import org.springframework.core.io.buffer.DataBuffer;
7+
import org.springframework.core.io.buffer.DataBufferFactory;
8+
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
69
import org.springframework.http.*;
7-
import org.springframework.http.client.ClientHttpRequestExecution;
8-
import org.springframework.scheduling.annotation.Scheduled;
10+
import org.springframework.http.client.ClientHttpRequest;
11+
import org.springframework.http.client.SimpleClientHttpRequestFactory;
912
import org.springframework.stereotype.Component;
1013
import org.springframework.util.Assert;
1114
import org.springframework.util.LinkedMultiValueMap;
1215
import org.springframework.util.MultiValueMap;
1316
import org.springframework.web.client.HttpClientErrorException;
17+
import org.springframework.web.client.RequestCallback;
18+
import org.springframework.web.client.ResponseExtractor;
1419
import org.springframework.web.client.RestTemplate;
1520
import org.springframework.web.util.UriComponentsBuilder;
21+
import reactor.core.publisher.Flux;
22+
import reactor.core.publisher.FluxSink;
23+
import reactor.core.scheduler.Schedulers;
1624
import run.ikaros.api.core.attachment.AttachmentDriver;
1725
import run.ikaros.plugin.pan115.Pan115Const;
1826
import run.ikaros.plugin.pan115.exception.Pan115RequestFailException;
@@ -22,18 +30,25 @@
2230
import run.ikaros.plugin.pan115.model.Pan115Result;
2331
import run.ikaros.plugin.pan115.utils.JsonUtils;
2432

33+
import java.io.IOException;
34+
import java.io.InputStream;
2535
import java.net.URI;
26-
import java.net.URLEncoder;
36+
import java.net.URLDecoder;
2737
import java.nio.charset.StandardCharsets;
2838
import java.time.LocalDateTime;
29-
import java.util.*;
39+
import java.util.ArrayList;
40+
import java.util.LinkedHashMap;
41+
import java.util.List;
42+
import java.util.Map;
43+
import java.util.concurrent.atomic.AtomicBoolean;
3044

3145
import static run.ikaros.plugin.pan115.Pan115Const.*;
3246

3347
@Slf4j
3448
@Component
3549
public class DefaultPan115Repository implements Pan115Repository {
36-
private final RestTemplate restTemplate = new RestTemplate();
50+
private final RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
51+
private final DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
3752
private final HttpHeaders headers = new HttpHeaders();
3853

3954
@Override
@@ -238,8 +253,126 @@ public String openVideoPlay(String pickCode) {
238253
}
239254
}
240255

241-
@Scheduled(fixedDelay = 5000) // 5秒
242-
public void fixedDelayTask() {
243-
log.info("Fixed delay task - " + new Date());
256+
@Override
257+
public Flux<DataBuffer> openUFileSteam(String pickCode) {
258+
Assert.hasText(pickCode, "'pickCode' must has text.");
259+
final String uFileDownUrl = openUFileDownUrl(pickCode);
260+
return streamFileWithRestTemplate(uFileDownUrl);
261+
// return Flux.create(sink -> {
262+
// Schedulers.boundedElastic().schedule(() -> {
263+
// try {
264+
// ResponseEntity<byte[]> response = restTemplate.getForEntity(
265+
// uFileDownUrl, byte[].class);
266+
// if (response.getStatusCode() == HttpStatus.OK &&
267+
// response.getBody() != null) {
268+
// // 一次性发送所有数据(适合小文件)
269+
// DataBuffer dataBuffer = dataBufferFactory.allocateBuffer(
270+
// response.getBody().length);
271+
// dataBuffer.write(response.getBody());
272+
// sink.next(dataBuffer);
273+
// sink.complete();
274+
// } else {
275+
// sink.error(new RuntimeException(
276+
// "请求失败,状态码: " + response.getStatusCode()));
277+
// }
278+
// } catch (Exception e) {
279+
// sink.error(e);
280+
// }
281+
// });
282+
// });
283+
}
284+
285+
286+
/**
287+
* 使用 RestTemplate 获取文件流,转换为 Flux<DataBuffer>
288+
*
289+
* @param fileUrl 文件URL
290+
* @param chunkSize 分块大小(字节),默认为 8192
291+
* @return Flux<DataBuffer>
292+
*/
293+
public Flux<DataBuffer> streamFileWithRestTemplate(String fileUrl, int chunkSize) {
294+
if (chunkSize <= 0) {
295+
chunkSize = 8192; // 默认8KB
296+
}
297+
298+
final int finalChunkSize = chunkSize;
299+
300+
return Flux.create(sink -> {
301+
// 使用 boundedElastic 调度器执行阻塞操作
302+
Schedulers.boundedElastic().schedule(() -> {
303+
try {
304+
String newUrl = fileUrl;
305+
if (StringUtils.isNoneBlank(newUrl)) {
306+
newUrl = URLDecoder.decode(newUrl, StandardCharsets.UTF_8);
307+
}
308+
log.debug("Open stream for url: {}", newUrl);
309+
restTemplate.execute(newUrl, HttpMethod.GET, new RequestCallback() {
310+
@Override
311+
public void doWithRequest(ClientHttpRequest request) throws IOException {
312+
request.getHeaders().addAll(headers);
313+
}
314+
},
315+
(ResponseExtractor<Void>) response -> {
316+
if (response.getStatusCode() != HttpStatus.OK) {
317+
sink.error(new RuntimeException(
318+
"请求失败,状态码: " + response.getStatusCode()));
319+
return null;
320+
}
321+
322+
try (InputStream inputStream = response.getBody()) {
323+
byte[] buffer = new byte[finalChunkSize];
324+
int bytesRead;
325+
AtomicBoolean isCanceled = new AtomicBoolean(false);
326+
327+
sink.onCancel(() -> {
328+
isCanceled.set(true);
329+
try {
330+
inputStream.close();
331+
} catch (IOException e) {
332+
// 忽略关闭异常
333+
}
334+
});
335+
336+
while (!isCanceled.get() &&
337+
(bytesRead = inputStream.read(buffer)) != -1) {
338+
339+
// 创建 DataBuffer
340+
DataBuffer dataBuffer = dataBufferFactory.allocateBuffer(bytesRead);
341+
dataBuffer.write(buffer, 0, bytesRead);
342+
343+
// 发布数据块
344+
sink.next(dataBuffer);
345+
346+
// 检查是否取消
347+
if (sink.isCancelled()) {
348+
log.debug("Close stream for url: {}", fileUrl);
349+
break;
350+
}
351+
}
352+
353+
if (!isCanceled.get()) {
354+
sink.complete();
355+
}
356+
} catch (Exception e) {
357+
if (!sink.isCancelled()) {
358+
sink.error(e);
359+
}
360+
}
361+
return null;
362+
});
363+
} catch (Exception e) {
364+
if (!sink.isCancelled()) {
365+
sink.error(e);
366+
}
367+
}
368+
});
369+
}, FluxSink.OverflowStrategy.BUFFER);
370+
}
371+
372+
/**
373+
* 简化版本:使用默认分块大小
374+
*/
375+
public Flux<DataBuffer> streamFileWithRestTemplate(String fileUrl) {
376+
return streamFileWithRestTemplate(fileUrl, 8192);
244377
}
245378
}

src/main/java/run/ikaros/plugin/pan115/repository/Pan115Repository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package run.ikaros.plugin.pan115.repository;
22

3+
import org.springframework.core.io.buffer.DataBuffer;
4+
import reactor.core.publisher.Flux;
35
import run.ikaros.api.core.attachment.AttachmentDriver;
46
import run.ikaros.plugin.pan115.model.Pan115Attachment;
57
import run.ikaros.plugin.pan115.model.Pan115Folder;
@@ -22,5 +24,5 @@ List<Pan115Attachment> openUFileFiles(String cid, Integer limit, Integer cur,
2224

2325
String openVideoPlay(String pickCode);
2426

25-
// void openVideoPlay(String pc);
27+
Flux<DataBuffer> openUFileSteam(String pickCode);
2628
}

src/main/resources/plugin.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ name: PluginPan115
44
# plugin entry class that extends BasePlugin
55
clazz: run.ikaros.plugin.pan115.Pan115Plugin
66
# plugin 'version' is a valid semantic version string (see semver.org).
7-
version: 1.0.6
8-
requires: ">=1.0.4"
7+
version: 1.0.7
8+
requires: ">=1.0.5"
99
author:
1010
name: Ikaros OSS Team
1111
website: https://github.com/ikaros-dev

0 commit comments

Comments
 (0)