66import com .xwintop .xJavaFxTool .model .PluginJarInfo ;
77import com .xwintop .xJavaFxTool .utils .Config ;
88import com .xwintop .xJavaFxTool .utils .Config .Keys ;
9- import com .xwintop .xJavaFxTool .utils .UserAgentUtils ;
109import com .xwintop .xJavaFxTool .utils .XJavaFxSystemUtil ;
10+ import lombok .extern .slf4j .Slf4j ;
11+ import okhttp3 .*;
12+ import okhttp3 .Request .Builder ;
13+ import okio .*;
14+ import org .apache .commons .io .FileUtils ;
15+ import org .apache .commons .io .IOUtils ;
16+
1117import java .io .File ;
1218import java .io .FileOutputStream ;
1319import java .io .IOException ;
2430import java .util .concurrent .CompletableFuture ;
2531import java .util .function .BiConsumer ;
2632import java .util .function .Consumer ;
27- import lombok .extern .slf4j .Slf4j ;
28- import okhttp3 .Interceptor ;
29- import okhttp3 .MediaType ;
30- import okhttp3 .OkHttpClient ;
31- import okhttp3 .Request .Builder ;
32- import okhttp3 .Response ;
33- import okhttp3 .ResponseBody ;
34- import okio .Buffer ;
35- import okio .BufferedSource ;
36- import okio .ForwardingSource ;
37- import okio .Okio ;
38- import okio .Source ;
39- import org .apache .commons .io .FileUtils ;
40- import org .apache .commons .io .IOUtils ;
4133
4234@ Slf4j
4335public class PluginManager {
@@ -48,6 +40,15 @@ public class PluginManager {
4840
4941 public static final Charset DEFAULT_CHARSET = StandardCharsets .UTF_8 ;
5042
43+ /**
44+ * 当下载插件时,模拟数种 UA
45+ */
46+ public static final String [] OPTIONAL_UA_LIST = {
47+ "Mozilla/5.0 (Windows NT 6.1; rv:51.0) Gecko/20100101 Firefox/51.0" ,
48+ "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.0 Safari/537.36" ,
49+ "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
50+ };
51+
5152 private static PluginManager instance ;
5253
5354 public static PluginManager getInstance () {
@@ -214,21 +215,27 @@ public File downloadPlugin(
214215 this .currentProgressListener =
215216 (bytesRead , contentLength , done ) -> onProgressUpdate .accept (contentLength , bytesRead );
216217
217- // 插件下载
218- int retryTimes = UserAgentUtils .getUserAgentSize ()-1 ;
219- Response response = null ;
220- while (retryTimes > 0 && (response == null || response .code () != HttpStatus .HTTP_OK )){
221- response = pluginDownloader .newCall (new Builder ().header ("User-Agent" , UserAgentUtils .getUserAgent (retryTimes )).url (pluginJarInfo .getDownloadUrl ()).build ()).execute ();
222- retryTimes --;
218+ // 使用多个 UA 尝试下载
219+ Throwable downloadFailure = null ;
220+ for (String ua : OPTIONAL_UA_LIST ) {
221+ try {
222+ tryDownload (pluginJarInfo .getDownloadUrl (), ua , file );
223+ downloadFailure = null ;
224+ break ;
225+ } catch (Exception e ) {
226+ downloadFailure = e ;
227+ }
223228 }
224- // 下载仍未成功,需要抛出异常,提示下载失败
225- if (response == null || response .code () != HttpStatus .HTTP_OK ){
226- throw new IOException ("插件下载失败 " + pluginJarInfo .getJarName ());
229+
230+ if (downloadFailure != null ) {
231+ if (downloadFailure instanceof IOException ) {
232+ throw (IOException ) downloadFailure ;
233+ } else {
234+ throw new IOException ("插件下载失败 " + pluginJarInfo .getJarName (), downloadFailure );
235+ }
227236 }
228- InputStream inputStream = response .body ().byteStream ();
229- FileOutputStream outputStream = new FileOutputStream (file );
230- IOUtils .copy (inputStream , outputStream );
231237
238+ // 下载完毕
232239 plugin .setIsDownload (true );
233240 plugin .setIsEnable (true );
234241 plugin .setLocalVersionNumber (plugin .getVersionNumber ());
@@ -240,8 +247,33 @@ public File downloadPlugin(
240247 return file ;
241248 }
242249
250+ /**
251+ * 尝试指定的 UA 进行下载,如果下载失败则抛出异常
252+ *
253+ * @param url 下载地址
254+ * @param ua UA 字符串
255+ * @param file 下载到的目标文件
256+ *
257+ * @throws IOException 如果下载失败
258+ */
259+ private void tryDownload (String url , String ua , File file ) throws IOException {
260+ Request request = new Builder ().header ("User-Agent" , ua ).url (url ).build ();
261+
262+ try (Response response = pluginDownloader .newCall (request ).execute ()) {
263+ if (response .code () != HttpStatus .HTTP_OK ) {
264+ throw new IOException ("插件下载失败 : HTTP " + response .code ());
265+ }
266+
267+ InputStream inputStream = Objects .requireNonNull (response .body ()).byteStream ();
268+ try (FileOutputStream outputStream = new FileOutputStream (file )) {
269+ IOUtils .copy (inputStream , outputStream );
270+ }
271+ }
272+ }
273+
243274 ////////////////////////////////////////////////////////////// 保存配置
244275
276+ // 保存配置,如果失败则抛出异常
245277 public void saveToFile () throws IOException {
246278 String json = JSON .toJSONString (this .pluginList , true );
247279 Path path = Paths .get (this .localPluginsPath );
@@ -251,6 +283,7 @@ public void saveToFile() throws IOException {
251283 Files .write (path , json .getBytes (DEFAULT_CHARSET ));
252284 }
253285
286+ // 保存配置,如果失败不抛出异常
254287 public void saveToFileQuietly () {
255288 try {
256289 saveToFile ();
@@ -313,6 +346,7 @@ public BufferedSource source() {
313346
314347 private Source source (Source source ) {
315348 return new ForwardingSource (source ) {
349+
316350 long totalBytesRead = 0L ;
317351
318352 @ Override
0 commit comments