飞书知识库备份

目录

1、创建应用,添加机器人能力,添加应用为知识库管理员。方法如图:

2、获取到知识空间ID。

3、Java代码(递归调用)


1、创建应用,添加机器人能力,添加应用为知识库管理员。方法如图:

2、获取到知识空间ID。

3、Java代码(递归调用)

java 复制代码
package xyz.jangle.feishu.test;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonParser;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.drive.v1.model.DownloadFileReq;
import com.lark.oapi.service.drive.v1.model.DownloadFileResp;
import com.lark.oapi.service.wiki.v2.model.ListSpaceNodeReq;
import com.lark.oapi.service.wiki.v2.model.ListSpaceNodeResp;

/**
 * 知识空间(知识库)备份
 * @author jangle
 * @email 274676957@qq.com
 * 2025年12月17日 上午10:38:34
 */
public class FeishuZSKMain {
	
	Client client;

	public FeishuZSKMain() {
		super();
		client = Client.newBuilder("App ID", "App Secret").build();
	}

	/**
	 * 1.遍历知识库
	 * 2025年12月17日 上午11:03:47 @author jangle
	 * @param spaceId	知识空间ID
	 * @param parentNodeToken	上级token
	 * @param path		文件路径
	 * @throws Exception
	 */
	public void getListSpaceNode(String spaceId,String parentNodeToken,String path,String pageToken) throws Exception {
		// 创建请求对象
	      ListSpaceNodeReq req = ListSpaceNodeReq.newBuilder()
	             .spaceId(spaceId)
	             .pageSize(50)
	             .pageToken(pageToken)
	             .parentNodeToken(parentNodeToken)
	             .build();
	      // 发起请求
	      ListSpaceNodeResp resp = client.wiki().v2().spaceNode().list(req);

	       // 处理服务端错误
	       if (!resp.success()) {
	         System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
	                    resp.getCode(), resp.getMsg(), resp.getRequestId(), Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
	         return;
	       }

	       // 业务数据处理
//	         System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
	       String json = Jsons.DEFAULT.toJson(resp.getData());
	       JSONObject data = JSONObject.parseObject(json);
	       JSONArray items = data.getJSONArray("items");
	       for (int i = 0; i < items.size(); i++) {
	        	 JSONObject item = items.getJSONObject(i);
	        	 if(item.getBoolean("has_child")) {
	        		 // 有子集,则向下遍历
//	        		 System.out.println("has_child:"+item.getBoolean("has_child"));
//	        		 System.out.println("obj_token:"+item.getString("obj_token"));
//	        		 System.out.println("title:"+item.getString("title"));
//	        		 System.out.println("node_token:"+item.getString("node_token"));
	        		 getListSpaceNode(spaceId, item.getString("node_token"), path+"/"+item.getString("title"),"");
	        	 }else {
	        		 try {
//						 Files.createDirectories(Paths.get(path));// 创建目录
	        			 File dir = new File(path);
	        			 if(!dir.exists()) {
	        				 System.out.println("创建目录:"+path);
	        				 dir.mkdirs();
	        			 }
//						 System.out.println(path+"/"+item.getString("title"));
						 String title = item.getString("title");
						 File file = new File(path+"/"+title);
//						 if(title.contains(".") && !Files.exists(Paths.get(path,title))) {
//						 if("file".equals(item.getString("obj_type")) && !Files.exists(Paths.get(path,title))) {
						 if("file".equals(item.getString("obj_type")) && !file.exists()) {
							System.out.println("下载:"+title);
	        			 	downloadFile(item.getString("obj_token"), path+"/"+title);	// 下载
						 }
	        		 } catch (Exception e) {
						e.printStackTrace();
	        		 }
	        	 }
			}
	        if(data.getBoolean("has_more")) {
	        	getListSpaceNode(spaceId, parentNodeToken, path, data.getString("page_token"));
	        }
	        
	}
	
	/**
	 * 2.下载文件
	 * 2025年12月17日 上午11:14:01 @author jangle
	 * @param objToken	文件token
	 * @param filepath	文件下载路径
	 */
	private void downloadFile(String objToken,String filepath)  {
		for(int i=0;i<3;i++) {
			try {
				// 创建请求对象
				DownloadFileReq req = DownloadFileReq.newBuilder()
						.fileToken(objToken)
						.build();
				// 发起请求
				DownloadFileResp resp = client.drive().v1().file().download(req);
				
				// 处理服务端错误
				if (!resp.success()) {
					System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
							resp.getCode(), resp.getMsg(), resp.getRequestId(), Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
					return;
				}
				// 业务数据处理
				resp.writeFile(filepath);
				return;
			} catch(Exception e) {
				e.printStackTrace();
				try {
                    TimeUnit.SECONDS.sleep(1 * (i + 1));
                } catch (InterruptedException ie) {
                	ie.printStackTrace();
                    Thread.currentThread().interrupt();
                    return;
                }
			}
		}
	}




	/**
	 * 0.主程序入口
	 * 2025年12月17日 上午10:38:34 @author jangle
	 * @param args
	 */
	public static void main(String[] args) {
		FeishuZSKMain main = new FeishuZSKMain();
		try {
			main.getListSpaceNode("732***********14146", "", "D:/filepath","");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
相关推荐
鹿角片ljp1 天前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
泡海椒1 天前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
景熙55231 天前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7041 天前
Spring Security权限控制
java·python·spring
杨运交1 天前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow1 天前
CountDownLatch in Java
java
SL_staff1 天前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程1 天前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff1 天前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈