11package com .xwintop .xJavaFxTool .services .index ;
22
3- import cn .hutool .http .HttpStatus ;
3+ import cn .hutool .core .io .StreamProgress ;
4+ import cn .hutool .http .HttpResponse ;
45import cn .hutool .http .HttpUtil ;
56import com .alibaba .fastjson .JSON ;
67import com .xwintop .xJavaFxTool .AppException ;
1617import lombok .Getter ;
1718import lombok .Setter ;
1819import lombok .extern .slf4j .Slf4j ;
19- import okhttp3 .*;
20- import okio .*;
2120import org .apache .commons .io .FileUtils ;
22- import org .apache .commons .io .IOUtils ;
2321import org .apache .commons .lang3 .BooleanUtils ;
2422import org .apache .commons .lang3 .StringUtils ;
2523
2624import java .io .File ;
27- import java .io .FileOutputStream ;
2825import java .io .IOException ;
29- import java .io .InputStream ;
3026import java .util .HashMap ;
3127import java .util .List ;
3228import java .util .Map ;
33- import java .util .Objects ;
3429import java .util .concurrent .CompletableFuture ;
3530import java .util .concurrent .ConcurrentHashMap ;
3631import java .util .function .BiConsumer ;
@@ -50,11 +45,11 @@ public class PluginManageService {
5045 /**
5146 * 当下载插件时,模拟数种 UA
5247 */
53- public static final String [] OPTIONAL_UA_LIST = {
54- "Mozilla/5.0 (Windows NT 6.1; rv:51.0) Gecko/20100101 Firefox/51.0" ,
55- "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.0 Safari/537.36" ,
56- "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
57- };
48+ // public static final String[] OPTIONAL_UA_LIST = {
49+ // "Mozilla/5.0 (Windows NT 6.1; rv:51.0) Gecko/20100101 Firefox/51.0",
50+ // "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.0 Safari/537.36",
51+ // "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
52+ // };
5853
5954 private PluginManageController pluginManageController ;
6055
@@ -115,13 +110,13 @@ protected void execute() throws Exception {
115110 progressTask .setOnFailed (event -> {
116111 Throwable e = event .getSource ().getException ();
117112 if (e != null ) {
118- log .error ("" , e );
113+ log .error ("下载插件失败 " , e );
119114 FxAlerts .error (controllerWindow , "下载插件失败" , e );
120115 } else {
121116 FxAlerts .error (controllerWindow , "下载失败" , event .getSource ().getMessage ());
122117 }
123118 });
124- dialog .show ();
119+ dialog .showAndWait ();
125120 }
126121
127122 public void setIsEnableTableColumn (Integer index ) {
@@ -204,116 +199,141 @@ public void deletePlugin() {
204199 }
205200 }
206201
207- public File downloadPlugin (PluginJarInfo pluginJarInfo , BiConsumer <Long , Long > onProgressUpdate ) throws IOException {
202+ public void downloadPlugin (PluginJarInfo pluginJarInfo , BiConsumer <Long , Long > onProgressUpdate ) throws IOException {
208203 File file = pluginJarInfo .getFile ();
209204 FileUtils .forceMkdirParent (file );
210- OkHttpClient pluginDownloader = new OkHttpClient .Builder ().addInterceptor (new PluginManageService .DownloadProgressInterceptor (onProgressUpdate )).build ();
211- // 使用多个 UA 尝试下载
212- Throwable downloadFailure = null ;
213- for (String ua : OPTIONAL_UA_LIST ) {
214- try {
215- tryDownload (pluginJarInfo .getName (), pluginJarInfo .getDownloadUrl (), ua , file , pluginDownloader );
216- downloadFailure = null ;
217- break ;
218- } catch (Exception e ) {
219- downloadFailure = e ;
205+ HttpResponse response = HttpUtil .createGet (pluginJarInfo .getDownloadUrl (), true ).executeAsync ();
206+ long contentLength = response .contentLength ();
207+ response .writeBodyForFile (file , new StreamProgress () {
208+ @ Override
209+ public void start () {
220210 }
221- }
222- if (downloadFailure != null ) {
223- if (downloadFailure instanceof IOException ) {
224- throw (IOException ) downloadFailure ;
225- } else {
226- throw new IOException ("插件 '" + pluginJarInfo .getName () + "' 下载失败 " + pluginJarInfo .getJarName (), downloadFailure );
211+
212+ @ Override
213+ public void progress (long progressSize ) {
214+ onProgressUpdate .accept (contentLength , progressSize );
227215 }
228- }
216+
217+ @ Override
218+ public void finish () {
219+ }
220+ });
229221 // 下载完毕
230222 pluginJarInfo .setIsDownload (true );
231223 pluginJarInfo .setIsEnable (true );
232224 pluginJarInfo .setLocalVersionNumber (pluginJarInfo .getVersionNumber ());
233- return file ;
234- }
235-
236- /**
237- * 尝试指定的 UA 进行下载,如果下载失败则抛出异常
238- *
239- * @param pluginName 插件名称
240- * @param url 下载地址
241- * @param ua UA 字符串
242- * @param file 下载到的目标文件
243- * @throws IOException 如果下载失败
244- */
245- private void tryDownload (String pluginName , String url , String ua , File file , OkHttpClient pluginDownloader ) throws IOException {
246- Request request = new Request .Builder ().header ("User-Agent" , ua ).url (url ).build ();
247- try (Response response = pluginDownloader .newCall (request ).execute ()) {
248- if (response .code () != HttpStatus .HTTP_OK ) {
249- throw new IOException ("插件 '" + pluginName + "' 下载失败 : HTTP " + response .code ());
250- }
251-
252- InputStream inputStream = Objects .requireNonNull (response .body ()).byteStream ();
253- try (FileOutputStream outputStream = new FileOutputStream (file )) {
254- IOUtils .copy (inputStream , outputStream );
255- }
256- }
257- }
258-
259- private class DownloadProgressInterceptor implements Interceptor {
260- private BiConsumer <Long , Long > onProgressUpdate ;
261-
262- DownloadProgressInterceptor (BiConsumer <Long , Long > onProgressUpdate ) {
263- this .onProgressUpdate = onProgressUpdate ;
264- }
265-
266- @ Override
267- public Response intercept (Chain chain ) throws IOException {
268- Response originalResponse = chain .proceed (chain .request ());
269- return originalResponse .newBuilder ()
270- .body (new PluginManageService .ProgressResponseBody (originalResponse .body (), onProgressUpdate )).build ();
271- }
272225 }
273226
274- private static class ProgressResponseBody extends ResponseBody {
275- private final ResponseBody responseBody ;
276-
277- private BiConsumer <Long , Long > onProgressUpdate ;
278-
279- private BufferedSource bufferedSource ;
280-
281- ProgressResponseBody (ResponseBody responseBody , BiConsumer <Long , Long > onProgressUpdate ) {
282- this .responseBody = responseBody ;
283- this .onProgressUpdate = onProgressUpdate ;
284- }
285-
286- @ Override
287- public MediaType contentType () {
288- return responseBody .contentType ();
289- }
290-
291- @ Override
292- public long contentLength () {
293- return responseBody .contentLength ();
294- }
295-
296- @ Override
297- public BufferedSource source () {
298- if (bufferedSource == null ) {
299- bufferedSource = Okio .buffer (source (responseBody .source ()));
300- }
301- return bufferedSource ;
302- }
303-
304- private Source source (Source source ) {
305- return new ForwardingSource (source ) {
306- long totalBytesRead = 0L ;
227+ // public File downloadPlugin(PluginJarInfo pluginJarInfo, BiConsumer<Long, Long> onProgressUpdate) throws IOException {
228+ // File file = pluginJarInfo.getFile();
229+ // FileUtils.forceMkdirParent(file);
230+ // OkHttpClient pluginDownloader = new OkHttpClient.Builder().addInterceptor(new PluginManageService.DownloadProgressInterceptor(onProgressUpdate)).build();
231+ // // 使用多个 UA 尝试下载
232+ // Throwable downloadFailure = null;
233+ // for (String ua : OPTIONAL_UA_LIST) {
234+ // try {
235+ // tryDownload(pluginJarInfo.getName(), pluginJarInfo.getDownloadUrl(), ua, file, pluginDownloader);
236+ // downloadFailure = null;
237+ // break;
238+ // } catch (Exception e) {
239+ // downloadFailure = e;
240+ // }
241+ // }
242+ // if (downloadFailure != null) {
243+ // if (downloadFailure instanceof IOException) {
244+ // throw (IOException) downloadFailure;
245+ // } else {
246+ // throw new IOException("插件 '" + pluginJarInfo.getName() + "' 下载失败 " + pluginJarInfo.getJarName(), downloadFailure);
247+ // }
248+ // }
249+ // // 下载完毕
250+ // pluginJarInfo.setIsDownload(true);
251+ // pluginJarInfo.setIsEnable(true);
252+ // pluginJarInfo.setLocalVersionNumber(pluginJarInfo.getVersionNumber());
253+ // return file;
254+ // }
255+ //
256+ // /**
257+ // * 尝试指定的 UA 进行下载,如果下载失败则抛出异常
258+ // *
259+ // * @param pluginName 插件名称
260+ // * @param url 下载地址
261+ // * @param ua UA 字符串
262+ // * @param file 下载到的目标文件
263+ // * @throws IOException 如果下载失败
264+ // */
265+ // private void tryDownload(String pluginName, String url, String ua, File file, OkHttpClient pluginDownloader) throws IOException {
266+ // Request request = new Request.Builder().header("User-Agent", ua).url(url).build();
267+ // try (Response response = pluginDownloader.newCall(request).execute()) {
268+ // if (response.code() != HttpStatus.HTTP_OK) {
269+ // throw new IOException("插件 '" + pluginName + "' 下载失败 : HTTP " + response.code());
270+ // }
271+ //
272+ // InputStream inputStream = Objects.requireNonNull(response.body()).byteStream();
273+ // try (FileOutputStream outputStream = new FileOutputStream(file)) {
274+ // IOUtils.copy(inputStream, outputStream);
275+ // }
276+ // }
277+ // }
307278
308- @ Override
309- public long read (Buffer sink , long byteCount ) throws IOException {
310- long bytesRead = super .read (sink , byteCount );
311- // read() returns the number of bytes read, or -1 if this source is exhausted.
312- totalBytesRead += bytesRead != -1 ? bytesRead : 0 ;
313- onProgressUpdate .accept (totalBytesRead , responseBody .contentLength ());
314- return bytesRead ;
315- }
316- };
317- }
318- }
279+ // private class DownloadProgressInterceptor implements Interceptor {
280+ // private BiConsumer<Long, Long> onProgressUpdate;
281+ //
282+ // DownloadProgressInterceptor(BiConsumer<Long, Long> onProgressUpdate) {
283+ // this.onProgressUpdate = onProgressUpdate;
284+ // }
285+ //
286+ // @Override
287+ // public Response intercept(Chain chain) throws IOException {
288+ // Response originalResponse = chain.proceed(chain.request());
289+ // return originalResponse.newBuilder()
290+ // .body(new PluginManageService.ProgressResponseBody(originalResponse.body(), onProgressUpdate)).build();
291+ // }
292+ // }
293+ //
294+ // private static class ProgressResponseBody extends ResponseBody {
295+ // private final ResponseBody responseBody;
296+ //
297+ // private BiConsumer<Long, Long> onProgressUpdate;
298+ //
299+ // private BufferedSource bufferedSource;
300+ //
301+ // ProgressResponseBody(ResponseBody responseBody, BiConsumer<Long, Long> onProgressUpdate) {
302+ // this.responseBody = responseBody;
303+ // this.onProgressUpdate = onProgressUpdate;
304+ // }
305+ //
306+ // @Override
307+ // public MediaType contentType() {
308+ // return responseBody.contentType();
309+ // }
310+ //
311+ // @Override
312+ // public long contentLength() {
313+ // return responseBody.contentLength();
314+ // }
315+ //
316+ // @Override
317+ // public BufferedSource source() {
318+ // if (bufferedSource == null) {
319+ // bufferedSource = Okio.buffer(source(responseBody.source()));
320+ // }
321+ // return bufferedSource;
322+ // }
323+ //
324+ // private Source source(Source source) {
325+ // return new ForwardingSource(source) {
326+ // long totalBytesRead = 0L;
327+ //
328+ // @Override
329+ // public long read(Buffer sink, long byteCount) throws IOException {
330+ // long bytesRead = super.read(sink, byteCount);
331+ // // read() returns the number of bytes read, or -1 if this source is exhausted.
332+ // totalBytesRead += bytesRead != -1 ? bytesRead : 0;
333+ // onProgressUpdate.accept(responseBody.contentLength(), totalBytesRead);
334+ // return bytesRead;
335+ // }
336+ // };
337+ // }
338+ // }
319339}
0 commit comments