MC中Mod整合包有时通过启动器无法正常安装,此时可以其中通过提供的manifest.json文件获取其在curseforge网站中的信息。文件中的projectID是Mod的ID,fileID是对应版本文件的ID,通过这两个值使用curseforgeAPI就可以查到对应的信息,例如:
"files": [
{
"projectID": 240630,
"fileID": 3336760,
"required": true
} ]
查看mod信息:https://addons-ecs.forgesvc.net/api/v2/addon/240630
查看mod文件信息:https://addons-ecs.forgesvc.net/api/v2/addon/240630/files
其中240630是projectID,这两个请求信息都是返回的Json格式信息,在mod文件信息中根据fileID 3336760就能够找到对应的MOD文件下载地址。使用的第三方jar包为:
Json文件处理:jackson-databind-2.8.6.jar
网络文件下载:commons-io-2.10.0.jar
日志处理:slf4j-log4j12-1.7.22.jar
输出Mod整合包中所有的Mod文件下载地址:
import java.io.*;
import java.net.URL;
import com.fasterxml.jackson.databind.*;
public class PrintModsUrl {
public static void main(String[] args) throws Exception{
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(new File("manifest.json"));
JsonNode files = root.get("files");
// 增加json节点并输出
// ObjectNode file = (ObjectNode) files.path(0);
// file.put("url", "https://edge.forgecdn.net/files/3336/760/JustEnoughResources-1.16.5-0.12.1.121.jar");
// OutputStream outputStream = new FileOutputStream(new File("murl.json"));
// mapper.writeValue(outputStream, root);
for (int i = 0; i < files.size(); i++) {
String pid = files.path(i).get("projectID").asText();
String fid = files.path(i).get("fileID").asText();
String webmodfile = "https://addons-ecs.forgesvc.net/api/v2/addon/" + pid + "/files";
JsonNode webroot;
try {
webroot = mapper.readTree(new URL(webmodfile));
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("errorpid:"+pid);
continue;
}
for (int j = 0; j < webroot.size(); j++) {
String webfid = webroot.path(j).get("id").asText();
if(webfid.equals(fid)) {
System.out.println(webroot.path(j).get("downloadUrl").asText());
}
}
}
}
}
下载工具类,此类是网上一个大佬写的,在此借用了并修改了,写此文章时没搜到原文件链接,特此感谢并致歉:
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class FileTools {
private static Logger logger = LoggerFactory.getLogger(FileTools.class);
/**
* 使用第三方jar包 org.apache.commons.io.FileUtils 简捷地下载网络文件
*
* @param urlStr 资源URL
* @param dir 存储目录
* @param fileName 存储文件名
* @return
*/
public static void downloadHttpResource(String urlStr, String fileName, String dir) {
try {
URL httpUrl = new URL(urlStr);
fileName = getFileName(httpUrl, fileName);
File dirFile = new File(dir);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
FileUtils.copyURLToFile(httpUrl, new File(dir + File.separator + fileName));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 下载网络文件,常规写法,不多说,直接上代码
*
* @param urlStr 资源URL
* @param dir 保存目录
* @param fileName 保存后的文件名,不包括后缀
* @return void
* @throws Exception
*/
public static void downloadNetResource(String urlStr, String fileName, String dir) throws Exception {
// 下载网络文件
int byteSum = 0;
int byteRead = 0;
InputStream inStream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
fileName = getFileName(url, fileName);
// 设置超时间为10秒
conn.setConnectTimeout(10 * 1000);
//模拟浏览器访问,防止屏蔽程序抓取而返回403错误
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36");
// 拿到输入流就相当于拿到了文件
inStream = conn.getInputStream();
// 文件保存位置
File saveDir = new File(dir);
if (!saveDir.exists()) {
saveDir.mkdir();
}
File file = new File(saveDir + File.separator + fileName);
if(file.exists())
return;
fos = new FileOutputStream(file);
byte[] buffer = new byte[1204];
while ((byteRead = inStream.read(buffer)) != -1) {
byteSum += byteRead;
fos.write(buffer, 0, byteRead);
}
logger.info("文件 {} 的大小为 {}", fileName, byteSum);
} catch (Exception e) {
logger.error("下载网络资源 {} 失败,请及时处理,", fileName, e);
throw e;
} finally {
IOUtils.closeQuietly(inStream, null);
IOUtils.closeQuietly(fos, null);
}
}
public static InputStream downloadNetResource(String urlStr) throws Exception {
InputStream inStream = null;
try {
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
// 设置超时间为30秒
conn.setConnectTimeout(30 * 1000);
//模拟浏览器访问,防止屏蔽程序抓取而返回403错误
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36");
// 拿到输入流就相当于拿到了文件
inStream = conn.getInputStream();
return inStream;
} catch (Exception e) {
throw e;
} finally {
// IOUtils.closeQuietly(inStream, null);
}
}
private static String getFileName(URL url, String fileName) {
if (StringUtils.isBlank(fileName)) {
fileName = Long.toString(System.currentTimeMillis());
}
String urlFileName = url.getFile();
logger.info("网络资源原始名称:{}", urlFileName);
// if (StringUtils.isNotEmpty(urlFileName)) {
// String subfix = urlFileName.substring(urlFileName.lastIndexOf("."));
// fileName = fileName + subfix;
// }
return fileName;
}
public static void main(String[] args) throws Exception {
String urlStr = "https://edge.forgecdn.net/files/3336/760/JustEnoughResources-1.16.5-0.12.1.121.jar";
int index = urlStr.lastIndexOf("/");
String fileName = urlStr.substring(index+1);
System.out.println(fileName);
String savePath = "/mods";
downloadNetResource(urlStr, fileName, savePath);
}
}
将前面输出的MOD下载url复制生成modurl.txt文件,执行以下代码进行下载:
import java.io.*;
import java.util.ArrayList;
public class DownLoadMods {
public static void main(String[] args) {
ArrayList<String> urls = toArrayByFileReader("modurl.txt");
for(String url:urls) {
int index = url.lastIndexOf("/");
String fileName = url.substring(index+1);
// System.out.println(fileName);
String savePath = "/mods";
try {
FileTools.downloadNetResource(url, fileName, savePath);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(url+"下载失败");
}
}
}
public static ArrayList<String> toArrayByFileReader(String name) {
// 使用ArrayList来存储每行读取到的字符串
ArrayList<String> arrayList = new ArrayList<>();
try {
FileReader fr = new FileReader(name);
BufferedReader bf = new BufferedReader(fr);
String str;
// 按行读取字符串
while ((str = bf.readLine()) != null) {
arrayList.add(str);
}
bf.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
return arrayList;
}
}