1. 認証と認可
2. リスト表示
3. ファイルクエリ
4. ファイルのプレビュー
5. ファイルのダウンロード
package net.aabg.dokisekai.utils.file;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.aabg.dokisekai.utils.file.baiducloud.bean.AllFIleInfo;
import net.aabg.dokisekai.utils.file.baiducloud.bean.FileInfo;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static net.aabg.dokisekai.utils.file.BDCD_Auth.APP_PATH;
import static net.aabg.dokisekai.utils.file.BDCD_Auth.getDeviceCode;
public class BaiduCloudDiskUtil {
public static void main(String[] args) {
upload();
}
/**
* 获取设备码,用户码
*/
public void getDevice() {
getDeviceCode();
}
public static void upload() {
String filePath = "/Users/snz/Documents/";
String fileName = "AirServer.dmg";
BDCD_Upload.upload(filePath, fileName);
}
}
/**
* 设备码授权模式
*/
class BDCD_Auth {
/**
* 应用名称
*/
public static String APP_NAME = "javatest";
/**
* 应用路径
*/
public static String APP_PATH = "/apps/" + APP_NAME + "/";//用于文件上传
public static String APP_LOCAL_TO_PATH = "/Users/snz/Documents/tmp/";//用于文件上传
/**
* 应用账号
*/
public static String APP_CLIENT_ID="";
/**
* 应用密钥
*/
public static String APP_CLIENT_SECRET="";
/**
* 授权token
*/
public static String APP_ACCESS_TOKEN = "token";
/**
* 刷新token
*/
public static String APP_REFRESH_TOKEN;
/**
* 设备码
*/
public static String DCODE;
//单位mb
// 普通用户单个分片大小固定为4MB(文件大小如果小于4MB,无需切片,直接上传即可),单文件总大小上限为4G。
//普通会员用户单个分片大小上限为16MB,单文件总大小上限为10G。
//超级会员用户单个分片大小上限为32MB,单文件总大小上限为20G。
public static Integer UNIT = 32;
// @Value("${baidu.cloud.disk.client_id}")
// public String tmp_client_id = "";
// @Value("${baidu.cloud.disk.client_secret}")
// public String tmp_client_secret = "";
//用作spring配置文件获取
// public void init() {
// APP_CLIENT_ID = tmp_client_id;
// APP_CLIENT_SECRET = tmp_client_secret;
// }
/**
* @return 获取设备码、用户码
*/
static JSONObject getDeviceCode() {
JSONObject jsonObject = BDCD_HttpUtils.get(BDCD_Api.DEVICE_CODE_API);
DCODE = jsonObject.get("device_code").toString();//获取设备码
BDCD_Api.REFRESH_TOKEN_API = jsonObject.get("qrcode_url").toString();//授权码,扫码认证
return jsonObject;
}
//3. 用 Device Code 轮询换取 Access Token
private static JSONObject getAccessToken() {
JSONObject jsonObject = BDCD_HttpUtils.get(BDCD_Api.TOKEN_API);
APP_ACCESS_TOKEN = jsonObject.get("access_token").toString();
APP_REFRESH_TOKEN = jsonObject.get("refresh_token").toString();
return jsonObject;
}
/**
* 刷新token
*/
public static JSONObject refreshToken() {
return BDCD_HttpUtils.get(BDCD_Api.REFRESH_TOKEN_API);
}
public static JSONObject userInfo() {
return BDCD_HttpUtils.get(BDCD_Api.USER_INFO_API);
}
public static JSONObject diskSize() {
return BDCD_HttpUtils.get(BDCD_Api.DISK_SIZE_API);
}
}
class BDCD_UserInfo {
public static String method = "uinfo";
public static String access_token = BDCD_Auth.APP_ACCESS_TOKEN;
public static void main(String[] args) {
getUserInfo();
getsize();
}
/*
* 获取用户信息
* */
public static void getUserInfo() {
try {
URL url = new URL("https://pan.baidu.com/rest/2.0/xpan/nas?method=" + method + "&access_token=" + access_token);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
} catch (Exception e) {
System.out.println(e);
}
}
/*
获取网盘容量信息
* checkfree int 否 1 URL参数 是否检查免费信息,0为不查,1为查,默认为0
* checkexpire int 否 1 URL参数 是否检查过期信息,0为不查,1为查,默认为0
* */
public static void getsize() {
try {
URL url = new URL("https://pan.baidu.com/api/quota?" +
"access_token=" + access_token +
"&checkfree=1" +
"&checkexpire=1");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
} catch (Exception e) {
System.out.println(e);
}
}
}
class BDCD_HttpUtils {
public static JSONObject get(String urlStr) {
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return JSONObject.parseObject(response.toString());
} catch (Exception e) {
System.out.println(e);
}
return null;
}
/**
* 构建完整get请求地址
*/
public static String buidGetUrl(String urlStr, Map<String, Object> parm) {
StringBuilder urlStrBuilder = new StringBuilder(urlStr);
for (String s : parm.keySet()) {
urlStrBuilder.append("&").append(s).append("=").append(parm.get(s));
}
urlStr = urlStrBuilder.toString();
return urlStr;
}
/**
* 构建完整get请求地址
*/
public static String encode(String str) {
try {
return URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* @Description: TODO 发送文件
* @param: url 发送地址
* @param: file 发送文件
* @return: java.lang.String
*/
public static String sendFile(String url, File file) {
try {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setContentType(ContentType.MULTIPART_FORM_DATA);
builder.addBinaryBody("file", file);
String body = "";
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
//设置请求参数
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, "utf-8");
}
EntityUtils.consume(entity);
//释放链接
response.close();
return body;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendFile(String url, String param, String file) {
if (url == null || param == null) {
return url;
}
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
//设置链接超时时间为2秒
conn.setConnectTimeout(1000);
//设置读取超时为2秒
conn.setReadTimeout(1000);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
out.write(file);
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println(e.getMessage() + "地址:" + url);
return null;
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
return null;
}
}
return result;
}
/**
* @Description: TODO
* @param: strURL 网址,可以是 http://aaa?bbb=1&ccc=2 拼接的
* @param: params 拼接的body参数也就是form表单的参数 ddd=1&eee=2
* @param: method 请求方式 get/post/put/delte等
* @return: java.lang.String
*/
public static String open(String strURL, String params, String method) {
try {
URL url = new URL(strURL);// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(method);
connection.setRequestProperty("Accept", "application/json");// 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/json");// 设置发送数据的格式
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8);// utf-8编码
out.append(params);
out.flush();
out.close(); // 读取响应
int length = connection.getContentLength();// 获取长度
InputStream is = connection.getInputStream();
if (length != -1) {
byte[] data = new byte[length];
byte[] temp = new byte[512];
int readLen = 0;
int destPos = 0;
while ((readLen = is.read(temp)) > 0) {
System.arraycopy(temp, 0, data, destPos, readLen);
destPos += readLen;
}
return new String(data, StandardCharsets.UTF_8);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class BDCD_FileInfo {
// 获取路径下文件信息
public static AllFIleInfo getFileList() {
Map parmMap = new HashMap<>();//请求参数
parmMap.put("access_token", BDCD_Auth.APP_ACCESS_TOKEN);//接口鉴权参数
parmMap.put("dir", BDCD_HttpUtils.encode("/"));//需要list的目录,以/开头的绝对路径, 默认为/
/*
* 排序字段:默认为name;
time表示先按文件类型排序,后按修改时间排序;
name表示先按文件类型排序,后按文件名称排序;
size表示先按文件类型排序,后按文件大小排序。
* */
parmMap.put("order", "name");
//默认为升序,设置为1实现降序 (注:排序的对象是当前目录下所有文件,不是当前分页下的文件)
parmMap.put("desc", 1);
//起始位置,从0开始
parmMap.put("start", 0);
//查询数目,默认为1000,建议最大不超过1000
parmMap.put("limit", 100);
//值为1时,返回dir_empty属性和缩略图数据
parmMap.put("web", 1);
// 是否只返回文件夹,0 返回所有,1 只返回文件夹,且属性只返回path字段
parmMap.put("folder", 0);
//是否返回dir_empty属性,0 不返回,1 返回
parmMap.put("showempty", 0);
String url = BDCD_HttpUtils.buidGetUrl(BDCD_Api.FILE_INFO_API, parmMap);
return JSONObject.parseObject(BDCD_HttpUtils.get(url).toString(), AllFIleInfo.class);
}
/**
* @return
*/
// 获取所有路径下文件信息
public static AllFIleInfo getAllFileList(String path) {
Map parmMap = new HashMap<>();//请求参数
parmMap.put("access_token", BDCD_Auth.APP_ACCESS_TOKEN);//接口鉴权参数
parmMap.put("path", BDCD_HttpUtils.encode("/交换区"));//需要list的目录,以/开头的绝对路径, 默认为/
parmMap.put("recursion", 0);//是否递归,0为否,1为是,默认为0
parmMap.put("order", "time");//排序字段:time(修改时间),name(文件名),size(大小,目录无大小),默认为文件类型
parmMap.put("desc", 0);//0为升序,1为降序,默认为0
parmMap.put("start", 0);//查询起点,默认为0
// parmMap.put("limit", 1000);//查询数目,默认为1000; 如果设置start和limit参数,则建议最大设置为1000
// parmMap.put("ctime", 1609430400);//文件上传时间,设置此参数,表示只返回上传时间大于ctime的文件
// parmMap.put("mtime", 0);//文件修改时间,设置此参数,表示只返回修改时间大于mtime的文件
parmMap.put("web", 0);//默认为0, 为1时返回缩略图地址
String url = BDCD_HttpUtils.buidGetUrl(BDCD_Api.FILE_INFO_ALL_API, parmMap);
return JSONObject.parseObject(BDCD_HttpUtils.get(url).toString(), AllFIleInfo.class);
}
/**
* @param key 搜索文件名
* @return
*/
//搜素文件
public static AllFIleInfo searchFile(String key) {
Map parmMap = new HashMap<>();//请求参数
parmMap.put("access_token", BDCD_Auth.APP_ACCESS_TOKEN);//接口鉴权参数
parmMap.put("key", key);//搜索关键字
parmMap.put("dir", BDCD_HttpUtils.encode("/交换区"));//搜索目录,默认根目录
parmMap.put("page", 1);//页数,从1开始,缺省则返回所有条目
parmMap.put("num", 100);//默认为500,不能修改
parmMap.put("recursion", 1);//是否递归搜索子目录 1:是,0:否(默认)
parmMap.put("web", 1);//默认0,为1时返回缩略图信息
String url = BDCD_HttpUtils.buidGetUrl(BDCD_Api.SEARCH_FILE_API, parmMap);
return JSONObject.parseObject(BDCD_HttpUtils.get(url).toString(), AllFIleInfo.class);
}
/**
* @param fsids [414244021542671,633507813519281]
* @return
* @mark 查询文件详情
*/
public static AllFIleInfo catFileInfo(String fsids) {
fsids = "[" + fsids + "]";
Map parmMap = new HashMap<>();//请求参数
parmMap.put("access_token", BDCD_Auth.APP_ACCESS_TOKEN);//接口鉴权参数
parmMap.put("fsids", fsids);//文件id数组,数组中元素是uint64类型,数组大小上限是:100
parmMap.put("dlink", 1);//是否需要下载地址,0为否,1为是,默认为0。获取到dlink后,参考下载文档进行下载操作
parmMap.put("path", BDCD_HttpUtils.encode("/"));//查询共享目录或专属空间内文件时需要。 共享目录格式: /uk-fsid ;其中uk为共享目录创建者id, fsid对应共享目录的fsid ;专属空间格式:/_pcs_.appdata/xpan/
parmMap.put("thumb", 1);//是否需要缩略图地址,0为否,1为是,默认为0
parmMap.put("extra", 1);//图片是否需要拍摄时间、原图分辨率等其他信息,0 否、1 是,默认0
parmMap.put("needmedia", 1);//视频是否需要展示时长信息,0 否、1 是,默认0
String url = BDCD_HttpUtils.buidGetUrl(BDCD_Api.FILE_METAS_API, parmMap);
AllFIleInfo fileInfo = JSONObject.parseObject(BDCD_HttpUtils.get(url).toString(), AllFIleInfo.class);
return fileInfo;
}
/**
* @param fsids
* @return
* @mark 构建多个文件信息获取
*/
public static AllFIleInfo catFileInfo(Set<String> fsids) {
StringBuilder fsidsStr = new StringBuilder();
for (String fsid : fsids) {
fsidsStr.append(fsid).append(",");
}
fsidsStr.substring(fsidsStr.length() - 1);
return catFileInfo(fsidsStr.toString());
}
}
class BDCD_Api {
/*==================================================认证授权===========================================================*/
/**
* 获取设备码
*/
public static String DEVICE_CODE_API = "https://openapi.baidu.com/oauth/2.0/device/code?response_type=device_code&scope=basic,netdisk&client_id="
+ BDCD_Auth.APP_CLIENT_ID;
/**
* 获取token-通过设备码
*/
public static String TOKEN_API = "https://openapi.baidu.com/oauth/2.0/token?" +
"grant_type=device_token" +
"&code=" + BDCD_Auth.DCODE +
"&client_id=" + BDCD_Auth.APP_CLIENT_ID +
"&client_secret=" + BDCD_Auth.APP_CLIENT_SECRET;
/**
* 扫码认证路径
*/
public static String AUTH_QRCODE_API;
/**
* 刷新token
*/
public static String REFRESH_TOKEN_API = "https://openapi.baidu.com/oauth/2.0/token?" +
"grant_type=refresh_token" +
"&refresh_token=" + BDCD_Auth.APP_REFRESH_TOKEN +
"&client_id=" + BDCD_Auth.APP_CLIENT_ID +
"&client_secret=" + BDCD_Auth.APP_CLIENT_SECRET;
/*==================================================用户信息===========================================================*/
public static String USER_INFO_API = "https://pan.baidu.com/rest/2.0/xpan/nas?method=uinfo&access_token=" + BDCD_Auth.APP_ACCESS_TOKEN;
public static String DISK_SIZE_API = "https://pan.baidu.com/api/quota?" +
"access_token=" + BDCD_Auth.APP_ACCESS_TOKEN +
"&checkfree=1" +
"&checkexpire=1";
/*==================================================文件信息===========================================================*/
public static String FILE_INFO_API = "https://pan.baidu.com/rest/2.0/xpan/file?method=list";
public static String FILE_INFO_ALL_API = "http://pan.baidu.com/rest/2.0/xpan/multimedia?method=listall";
public static String SEARCH_FILE_API = "http://pan.baidu.com/rest/2.0/xpan/file?method=search";
public static String FILE_METAS_API = "http://pan.baidu.com/rest/2.0/xpan/multimedia?method=filemetas";
/*==================================================文件上传===========================================================*/
//预上传
public static String READY_UPLOAD_API = "https://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token==" + BDCD_Auth.APP_ACCESS_TOKEN;
/**
* 文件上传
*/
public static String UPLOAD_API = "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?method=upload";
/**
* 文件创建
*/
public static final String CREATE_FILE = "https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token=" + BDCD_Auth.APP_ACCESS_TOKEN;
/*==================================================文件下载===========================================================*/
/**
* 文件下载
*/
public static String DOWN_API = "https://d.pcs.baidu.com/file/1261d72d03471f7b7b805fd60e024b8d?" +
"access_token=" + BDCD_Auth.APP_ACCESS_TOKEN;
}
@Slf4j
class BDCD_Upload {
public static String URL_UPLOAD = "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2";
//预上传
public static String URL_READY_URL_UPLOAD_FILE = "https://pan.baidu.com/rest/2.0/xpan/file";
// @SneakyThrows
public static void upload(String filePath, String fileName) {
File file = new File(filePath + fileName);//获取文件
File[] files = new File[0];//
try {
files = split(filePath, fileName);
} catch (Exception e) {
throw new RuntimeException(e);
}
StringBuffer md5s = FileUtils.splitMd5(files);
String cloudPath = APP_PATH + fileName;
//预上传
String precreate = precreate(cloudPath, file.length(), 0, md5s.toString());
log.info("预上传{}", precreate);//获取uploadid
String uploadid = (String) new cn.hutool.json.JSONObject(precreate).get("uploadid");
//分片上传
String upload = upload(cloudPath, uploadid, files);
log.info("分片上传{}", upload);
//创建文件
String create = create(fileName, file.length(), 0, md5s.toString(), uploadid);
log.info("创建文件{}", create);
for (File file1 : files) {
file1.delete();
}
String fid = JSON.parseObject(create, FileInfo.class).getFs_id();
//获取下载地址
String dlink = BDCD_FileInfo.catFileInfo(fid).getList().get(0).getDlink();
System.out.println(dlink);
log.info("文件下载地址", dlink);
}
//文件分片
public static File[] split(String filePath, String fileName) throws Exception {
String localFilePath = filePath + fileName;
String to = "/Users/snz/Documents/tmp/";
//文件分片并获取md5值
// File[] separate = FileUtils.separate(localFilePath, BDCD_Auth.UNIT);//分片
List<String> filesSet = FileSpiltAndMerge.spilt(localFilePath, BDCD_Auth.UNIT, to);//分片
File[] files = new File[filesSet.size()];
for (int i = 0; i < filesSet.size(); i++) {
files[i] = new File(filesSet.get(i));
}
return files;
}
/**
* @Description: TODO 预上传
* @param: cloudPath 云端路径
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
* @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
* @return: java.lang.String
*/
private static String precreate(String cloudPath, Long size, Integer isDir, String blockList) {
String strURL = URL_READY_URL_UPLOAD_FILE + "?method=precreate&access_token=" + BDCD_Auth.APP_ACCESS_TOKEN;
String params = "path=" + cloudPath + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir;
return BDCD_HttpUtils.open(strURL, params, "POST");
}
//文件预上传
//文件上传
//文件合并
/**
* @Description: TODO 创建文件
* @param: fileName 文件名称
* @param: size 文件大小 字节
* @param: isDir 0文件 1目录(设置为目录是 size要设置为0)
* @param: blockList (文件的md5值) 可以把文件分为多个,然后分批上传
* @return: java.lang.String
*/
private static String create(String fileName, Long size, Integer isDir, String blockList, String uploadid) {
String strURL = "https://pan.baidu.com/rest/2.0/xpan/file" + "?method=create&access_token=" + BDCD_Auth.APP_ACCESS_TOKEN;
String params = "path=" + APP_PATH + fileName + "&size=" + size + "&autoinit=1&block_list=[\"" + blockList + "\"]&isdir=" + isDir +
"&uploadid=" + uploadid;
return BDCD_HttpUtils.open(strURL, params, "POST");
}
/**
* @Description: TODO 分片上传
* @param: path 上传到百度网盘的地址
* @param: uploadid 上传的id
* @param: filePath 本地文件的地址
* @return: java.lang.String
*/
private static String upload(String path, String uploadid, File[] files) {
try {
for (int i = 0; i < files.length; i++) {
String url = "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?method=upload" +
"&access_token=" + BDCD_Auth.APP_ACCESS_TOKEN +
"&type=tmpfile&partseq=" + i +
"&path=" + path +
"&uploadid=" + uploadid;
String s = BDCD_HttpUtils.sendFile(url, files[i]);
log.info("正在上传分片文件{}{}", s, i);
}
return path;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
/*文件分片*/
class FileSpiltAndMerge {
public static List<String> spilt(String from, int size, String to) throws Exception {
List<String> files = new ArrayList<>();
File f = new File(from);
FileInputStream in = new FileInputStream(f);
FileOutputStream out = null;
FileChannel inChannel = in.getChannel();
FileChannel outChannel = null;
// 将MB单位转为为字节B
long m = size * 1024 * 1024;
// 计算最终会分成几个文件
int count = (int) (f.length() / m);
for (int i = 0; i <= count; i++) {
// 生成文件的路径
String t = to + "/AAA" + i;
files.add(t);
try {
out = new FileOutputStream(new File(t));
outChannel = out.getChannel();
// 从inChannel的m*i处,读取固定长度的数据,写入outChannel
if (i != count)
inChannel.transferTo(m * i, m, outChannel);
else// 最后一个文件,大小不固定,所以需要重新计算长度
inChannel.transferTo(m * i, f.length() - m * count, outChannel);
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
outChannel.close();
}
}
in.close();
inChannel.close();
return files;
}
public static void merge(String from, String to) throws IOException {
File t = new File(to);
FileInputStream in = null;
FileChannel inChannel = null;
FileOutputStream out = new FileOutputStream(t, true);
FileChannel outChannel = out.getChannel();
File f = new File(from);
// 获取目录下的每一个文件名,再将每个文件一次写入目标文件
if (f.isDirectory()) {
List<File> list = getAllFileAndSort(from);
// 记录新文件最后一个数据的位置
long start = 0;
for (File file : list) {
in = new FileInputStream(file);
inChannel = in.getChannel();
// 从inChannel中读取file.length()长度的数据,写入outChannel的start处
outChannel.transferFrom(inChannel, start, file.length());
start += file.length();
in.close();
inChannel.close();
}
}
out.close();
outChannel.close();
}
private static List<File> getAllFileAndSort(String dirPath) {
File dirFile = new File(dirPath);
File[] listFiles = dirFile.listFiles();
List<File> list = Arrays.asList(listFiles);
Collections.sort(list, (o1, o2) -> {
return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
});
return list;
}
}