OneDrive 支持

This commit is contained in:
zhaojun1998
2020-01-19 21:58:02 +08:00
parent ad0ad12c08
commit dcc4cb19ad
13 changed files with 383 additions and 58 deletions

View File

@@ -0,0 +1,75 @@
package im.zhaojun.common.config;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.constant.StorageConfigConstant;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.AbstractFileService;
import im.zhaojun.common.service.StorageConfigService;
import im.zhaojun.common.service.SystemConfigService;
import im.zhaojun.onedrive.service.OneDriveService;
import im.zhaojun.onedrive.service.OneDriveServiceImpl;
import im.zhaojun.onedrive.service.OneDriveToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
/**
* @author zhaojun
*/
@Configuration
@EnableScheduling
@Slf4j
public class GlobalScheduleTask {
@Resource
private StorageConfigService storageConfigService;
@Resource
private OneDriveService oneDriveService;
@Resource
private SystemConfigService systemConfigService;
/**
* 项目启动 30 秒后, 每半小时执行一次刷新 OneDrive Token 的定时任务.
*/
@Scheduled(fixedRate = 1000 * 60 * 30, initialDelay = 1000 * 30)
public void autoRefreshOneDriveToken() {
AbstractFileService currentFileService = systemConfigService.getCurrentFileService();
if (!(currentFileService instanceof OneDriveServiceImpl)) {
log.debug("当前启用存储类型, 不是 OneDrive, 跳过自动刷新 AccessToken");
return;
}
if (currentFileService.getIsUnInitialized()) {
log.debug("当前启用 OneDrive 未初始化成功, 跳过自动刷新 AccessToken");
return;
}
refreshOneDriveToken();
}
/**
* 调用刷新 OneDrive Token
*/
public void refreshOneDriveToken() {
OneDriveToken refreshToken = oneDriveService.getRefreshToken();
StorageConfig accessTokenConfig =
storageConfigService.selectByTypeAndKey(StorageTypeEnum.ONE_DRIVE, StorageConfigConstant.ACCESS_TOKEN_KEY);
StorageConfig refreshTokenConfig =
storageConfigService.selectByTypeAndKey(StorageTypeEnum.ONE_DRIVE, StorageConfigConstant.REFRESH_TOKEN_KEY);
accessTokenConfig.setValue(refreshToken.getAccessToken());
refreshTokenConfig.setValue(refreshToken.getRefreshToken());
storageConfigService.updateStorageConfig(Arrays.asList(accessTokenConfig, refreshTokenConfig));
log.info("刷新 OneDrive key 时间: " + LocalDateTime.now());
}
}

View File

@@ -27,6 +27,7 @@ public class StorageConfig {
private String title;
@Column(length = 2048)
private String value;
public Integer getId() {

View File

@@ -30,4 +30,8 @@ public class StorageConfigConstant {
public static final String FILE_PATH_KEY = "filePath";
}
public static final String ACCESS_TOKEN_KEY = "accessToken";
public static final String REFRESH_TOKEN_KEY = "refreshToken";
}

View File

@@ -1,24 +1,28 @@
package im.zhaojun.common.model.enums;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhaojun
*/
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum StorageTypeEnum {
/**
* 当前系统支持的所有存储策略
*/
UPYUN("upyun", "又拍云 USS"),
QINIU("qiniu", "七牛云 KODO"),
HUAWEI("huawei", "华为云 OBS"),
ALIYUN("aliyun", "阿里云 OSS"),
FTP("ftp", "FTP"),
HUAWEI("huawei", "华为云 OBS"),
LOCAL("local", "本地存储"),
MINIO("minio", "MINIO"),
ONE_DRIVE("onedrive", "OneDrive"),
QINIU("qiniu", "七牛云 KODO"),
TENCENT("tencent", "腾讯云 COS"),
MINIO("minio", "MINIO");
UPYUN("upyun", "又拍云 USS");
private String key;
private String description;

View File

@@ -20,4 +20,12 @@ public interface StorageConfigRepository extends JpaRepository<StorageConfig, In
*/
List<StorageConfig> findByTypeOrderById(StorageTypeEnum type);
/**
* 根据存储类型找到某个 KEY 的值
* @param type 存储类型
* @param key KEY
* @return KEY 对应的对象
*/
StorageConfig findByTypeAndKey(StorageTypeEnum type, String key);
}

View File

@@ -23,6 +23,12 @@ public class StorageConfigService {
return storageConfigRepository.findByTypeOrderById(storageTypeEnum);
}
public StorageConfig selectByTypeAndKey(StorageTypeEnum storageType, String key) {
return storageConfigRepository.findByTypeAndKey(storageType, key);
}
public Map<String, StorageConfig> selectStorageConfigMapByKey(StorageTypeEnum storageTypeEnum) {
Map<String, StorageConfig> map = new HashMap<>(24);
for (StorageConfig storageConfig : selectStorageConfigByType(storageTypeEnum)) {
@@ -31,6 +37,7 @@ public class StorageConfigService {
return map;
}
public void updateStorageConfig(List<StorageConfig> storageConfigList) {
storageConfigRepository.saveAll(storageConfigList);
}

View File

@@ -11,13 +11,13 @@ import org.springframework.web.client.RestTemplate;
public class HttpUtil {
public static String getTextContent(String url) {
RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);
RestTemplate restTemplate = SpringContextHolder.getBean("restTemplate");
String result = restTemplate.getForObject(url, String.class);
return result == null ? "" : result;
}
public static boolean checkUrlExist(String url) {
RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);
RestTemplate restTemplate = SpringContextHolder.getBean("restTemplate");
try {
restTemplate.headForHeaders(url);
return true;

View File

@@ -1,35 +1,41 @@
// package im.zhaojun.onedrive.config;
//
// import org.nuxeo.onedrive.client.*;
// import org.springframework.context.annotation.Configuration;
//
// @Configuration
// public class OneDriveConfig {
//
//
// public void a () {
// OneDriveAPI api = new OneDriveBasicAPI("YOUR_ACCESS_TOKEN");
//
// OneDriveFolder folder = new OneDriveFolder(api, "FOLDER_ID");
// OneDriveFile file = new OneDriveFile(api, "FILE_ID");
// }
//
// public static void main(String[] args) throws OneDriveAPIException {
// OneDriveBasicAPI api = new OneDriveBasicAPI("EwAgA61DBAAUcSSzoTJJsy+XrnQXgAKO5cj4yc8AAQ0ZknDUY8YnwB9aJv7vA9YjiRAVMnKc+rG11fSXLZRAA8Q/CgJaz+OkRN60vaLDfp6KxbmVlob6kxeD/peOUI2eHtk0055Q2+n057tlyVAvGIFl9dvqkItoAthjmybcSkKBZS5h1meWxQ5IOvzSVrdgCKL0NOtTxfh33ZUDsYjvSid6NOX4Bs+pRjvZhQkvqEfGt8KlOL+JoIowmv2I+u09iDmS60BMwSoeK2K3CCLIXxLaiiPYUMsrNk65j4PWEBwBEfyHb6j3lrM/YvwFLq7Y8KJVjrXjFENC7ruja6Ko/cfTMX90yLkUEckpsZ30E6RJHWEHt7jXtNwndDZVknYDZgAACL5pnk17FJfb8AGGxJL1Y0CnAzgkTM2gw+WkFRRDDNzujuW1LQofwZ119HdeANhPrBZ14x32VaPGL1l0RvtR9LCeAN+EogcV5xhVpmCExitaXQB6OkZ6BnXaxLj5TNvFRNeZq0ZfJ3T08clLA1vXHkZhNKgiFDI8xUbahy4r6QpzgoF+0+dz+MA1NzQCQCsRGieS63OD1BKrzRsNxzls5Z9rKzBT6CpWpiaiOg4mmW0yeino/L9zz9Gf5kAJr813bpNr+rH/E8MPd0pZf+6hv37FaVCM7RN1V7CkkCDnRAxwxEK8pDgZhRjZOw7gKutPOiOoTO9ptjh2Jcrds714HitX2HI3RsRY+yyAOcb8XI27m4daSEGCJCuu/TJwXTE4ul54MWsi8MrcDlZN9DOjckiJIqVI8IbvhM+OUAP4FUIfZJJrIVa8WFwxcsMmjlLTxp/I7+JfdvZjJSk3j1yYvbWFviyoSkpQgw2hIDhZxCg083Z6qS467g5H9Uz3fQc+Ss0K0Mud6RcZTU9RqCcp+h92tUc8+gDxQ2NwJsG5vcmSRwf5KHKvsWjt6yK4OHxCpkLYi31eJZtv2EjQGXX1gYyhc/2wQ+cHPvbgBzIfhXetbZKpSxoowAQO/J1i5oRs90h24kjTd4qJd3qspxk1lhZcEC8IkfZXjNgjEQI=");
//
// OneDriveFolder folder = new OneDriveFolder(api, "PDF");
//
// for (OneDriveItem.Metadata metadata : OneDriveFolder.getRoot(api)) {
// System.out.println(metadata.getName());
// if (metadata.isFile()) {
// }
// }
//
// // for (OneDriveItem.Metadata search : OneDriveFolder.getRoot(api).search("index.html")) {
// // System.out.println(search.getName());
// // }
//
// // OneDriveFile file = new OneDriveFile(api, "key.txt");
// // System.out.println(file);
// }
// }
package im.zhaojun.onedrive.config;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.constant.StorageConfigConstant;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.StorageConfigService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.Collections;
/**
* @author zhaojun
* @date 2020/1/18 17:13
*/
@Configuration
public class OneDriveConfig {
@Resource
private StorageConfigService storageConfigService;
@Bean
public RestTemplate oneDriveRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, clientHttpRequestExecution) -> {
StorageConfig accessTokenConfig =
storageConfigService.selectByTypeAndKey(StorageTypeEnum.ONE_DRIVE, StorageConfigConstant.ACCESS_TOKEN_KEY);
String tokenValue = String.format("%s %s", "Bearer", accessTokenConfig.getValue());
httpRequest.getHeaders().add("Authorization", tokenValue);
return clientHttpRequestExecution.execute(httpRequest, bytes);
};
restTemplate.setInterceptors(Collections.singletonList(interceptor));
return restTemplate;
}
}

View File

@@ -1,32 +1,30 @@
package im.zhaojun.onedrive.controller;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import im.zhaojun.onedrive.service.OneDriveService;
import im.zhaojun.onedrive.service.OneDriveToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.annotation.Resource;
/**
* @author zhaojun
*/
@Controller
@RequestMapping("/onedirve")
public class OneDriveController {
@GetMapping("/onedirve/callback")
@ResponseBody
public String onedriveCallback(String code, HttpServletRequest request) {
String json = "client_id=04a73532-6c16-4fe4-92e5-f2cd125ed553&redirect_uri=http://localhost:8080/onedirve/callback&client_secret=2gY/t?*Eff6i36TgKTtiG*08/k]@.I4[&code=" + code + "&grant_type=authorization_code";
@Resource
private OneDriveService oneDriveService;
HttpRequest post = HttpUtil.createPost("https://login.microsoftonline.com/common/oauth2/v2.0/token");
post.body(json, "application/x-www-form-urlencoded");
HttpResponse response = post.execute();
System.out.println(response.body());
return response.body();
@GetMapping("/callback")
public String onedriveCallback(String code, Model model) {
OneDriveToken oneDriveToken = oneDriveService.getToken(code);
model.addAttribute("accessToken", oneDriveToken.getAccessToken());
model.addAttribute("refreshToken", oneDriveToken.getRefreshToken());
return "callback";
}
}

View File

@@ -0,0 +1,124 @@
package im.zhaojun.onedrive.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.constant.StorageConfigConstant;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.enums.FileTypeEnum;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.repository.StorageConfigRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhaojun
* @date 2020/1/12 12:17
*/
@Service
public class OneDriveService {
public static final String DRIVER_INFO_URL = "https://graph.microsoft.com/v1.0/drive";
public static final String DRIVER_ROOT_URL = "https://graph.microsoft.com/v1.0/drive/root/children";
public static final String DRIVER_ITEMS_URL = "https://graph.microsoft.com/v1.0/drive/root:{path}:/children";
public static final String AUTHENTICATE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
@Value("${zfile.onedirve.clientId}")
private String clientId;
@Value("${zfile.onedirve.redirectUri}")
private String redirectUri;
@Value("${zfile.onedirve.clientSecret}")
private String clientSecret;
@Value("${zfile.onedirve.scope}")
private String scope;
@Resource
private RestTemplate oneDriveRestTemplate;
@Resource
private StorageConfigRepository storageConfigRepository;
public OneDriveToken getToken(String code) {
String param = "client_id=" + clientId +
"&redirect_uri=" + redirectUri +
"&client_secret=" + clientSecret +
"&code=" + code +
"&scope=" + scope +
"&grant_type=authorization_code";
HttpRequest post = HttpUtil.createPost(AUTHENTICATE_URL);
post.body(param, "application/x-www-form-urlencoded");
HttpResponse response = post.execute();
return JSONObject.parseObject(response.body(), OneDriveToken.class);
}
public OneDriveToken getRefreshToken() {
StorageConfig refreshStorageConfig =
storageConfigRepository.findByTypeAndKey(StorageTypeEnum.ONE_DRIVE, StorageConfigConstant.REFRESH_TOKEN_KEY);
String param = "client_id=" + clientId +
"&redirect_uri=" + redirectUri +
"&client_secret=" + clientSecret +
"&refresh_token=" + refreshStorageConfig.getValue() +
"&grant_type=refresh_token";
HttpRequest post = HttpUtil.createPost(AUTHENTICATE_URL);
post.body(param, "application/x-www-form-urlencoded");
HttpResponse response = post.execute();
return JSONObject.parseObject(response.body(), OneDriveToken.class);
}
public String getUserInfo() {
return oneDriveRestTemplate.getForObject(DRIVER_INFO_URL, String.class);
}
public List<FileItemDTO> list(String path) {
ResponseEntity<String> responseEntity = oneDriveRestTemplate.getForEntity("/".equalsIgnoreCase(path) ? DRIVER_ROOT_URL : DRIVER_ITEMS_URL, String.class, path);
String body = responseEntity.getBody();
JSONObject root = JSON.parseObject(body);
JSONArray fileList = root.getJSONArray("value");
List<FileItemDTO> result = new ArrayList<>();
for (int i = 0; i < fileList.size(); i++) {
FileItemDTO fileItemDTO = new FileItemDTO();
JSONObject fileItem = fileList.getJSONObject(i);
fileItemDTO.setName(fileItem.getString("name"));
fileItemDTO.setSize(fileItem.getLong("size"));
fileItemDTO.setTime(fileItem.getDate("lastModifiedDateTime"));
if (fileItem.containsKey("file")) {
fileItemDTO.setUrl(fileItem.getString("@microsoft.graph.downloadUrl"));
fileItemDTO.setType(FileTypeEnum.FILE);
} else {
fileItemDTO.setType(FileTypeEnum.FOLDER);
}
fileItemDTO.setPath(path);
result.add(fileItemDTO);
}
return result;
}
}

View File

@@ -0,0 +1,76 @@
package im.zhaojun.onedrive.service;
import im.zhaojun.common.config.GlobalScheduleTask;
import im.zhaojun.common.model.StorageConfig;
import im.zhaojun.common.model.constant.StorageConfigConstant;
import im.zhaojun.common.model.dto.FileItemDTO;
import im.zhaojun.common.model.enums.StorageTypeEnum;
import im.zhaojun.common.service.AbstractFileService;
import im.zhaojun.common.service.FileService;
import im.zhaojun.common.service.StorageConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* @author zhaojun
* @date 2020/1/12 13:53
*/
@Service
@Slf4j
public class OneDriveServiceImpl extends AbstractFileService implements FileService {
public static final String SYSTEM_ONEDRIVE_CACHE_PREFIX = "zfile-onedrive-cache:";
public static final String SYSTEM_ONEDRIVE_CACHE_ASSESS_TOKEN_KEY = "accessToken";
public static final String SYSTEM_ONEDRIVE_CACHE_REFRESH_TOKEN_KEY = "refreshToken";
@Resource
private GlobalScheduleTask globalScheduleTask;
@Resource
private StorageConfigService storageConfigService;
@Resource
private OneDriveService oneDriveService;
@Override
public void init() {
try {
Map<String, StorageConfig> stringStorageConfigMap =
storageConfigService.selectStorageConfigMapByKey(StorageTypeEnum.ONE_DRIVE);
String accessToken = stringStorageConfigMap.get(StorageConfigConstant.ACCESS_TOKEN_KEY).getValue();
String refreshToken = stringStorageConfigMap.get(StorageConfigConstant.REFRESH_TOKEN_KEY).getValue();
if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(refreshToken)) {
log.debug("初始化存储策略 [{}] 失败: 参数不完整", getStorageTypeEnum().getDescription());
isInitialized = false;
} else {
globalScheduleTask.refreshOneDriveToken();
isInitialized = testConnection();
}
} catch (Exception e) {
log.debug(getStorageTypeEnum().getDescription() + " 初始化异常, 已跳过");
}
}
@Override
public List<FileItemDTO> fileList(String path) {
return oneDriveService.list(path);
}
@Override
public String getDownloadUrl(String path) {
return null;
}
@Override
public StorageTypeEnum getStorageTypeEnum() {
return StorageTypeEnum.ONE_DRIVE;
}
}

View File

@@ -0,0 +1,18 @@
package im.zhaojun.onedrive.service;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* @author zhaojun
* @date 2020/1/18 17:28
*/
@Data
public class OneDriveToken {
@JSONField(name = "access_token")
private String accessToken;
@JSONField(name = "refresh_token")
private String refreshToken;
}