SpringBoot实现OneDrive文件上传
什么是 OneDrive?
OneDrive 原名 SkyDrive,是微软 Office 家族中的一个成员。使用 OneDrive,可将图片、文件和文件夹安全存储在一个位置,与其他人共享,并从任意位置访问它们。(类似于百度云盘/阿里云盘)
概述
-
查看 OneDrive 中存储的文件和图片。
-
在计算机上创建文档,并在笔记本计算机、手机或平板电脑上进行编辑。
-
共享文件和图片。
-
与他人同时协作处理 Office 文件。
源码
OneDriveUpload: SpringBoot实现OneDrive文件上传
参考文档
获取accessToken文档:针对 OneDrive API 的 Microsoft 帐户授权 - OneDrive dev center | Microsoft Learn
上传文件文档:上传小文件 - OneDrive API - OneDrive dev center | Microsoft Learn
所用的接口列表
获取CODE接口(GET):
https://login.live.com/oauth20_authorize.srf
参数列表
client_id:客户端id
scope:作用域,填files.readwrite offline_access即可
response_type:响应类型,填code即可
redirect_uri:重定向地址
通过code获取访问令牌和refresh_token(POST):https://login.live.com/oauth20_token.srf
参数列表
client_id:客户端id
redirect_uri:重定向地址
client_secret:客户端密钥
code:通过获取CODE接口获取的值
grant_type:授权类型,填authorization_code即可
通过refresh_token刷新访问令牌 (POST):https://login.live.com/oauth20_token.srf
参数列表
client_id:客户端id
redirect_uri:重定向地址
client_secret:客户端密钥
refresh_token:refresh_token
grant_type:授权类型,填refresh_token即可
文件上传(PUT):https://graph.microsoft.com/v1.0/me/drive/root:/uploadfile/3.png:/content其中uploadfile代表上传的文件夹,3.png代表文件名,都可以替换你自己的,文件夹没有会自动创建!
请求头参数:
Authorization:访问令牌(Bearer EwBgA8l6BAAUs5+HQn0N+h2FxWzLS31ZgQVuHsYAAW1mq2vZtoei5NmrcQfph5LLoTV0CYcPds89rOHiI1kYax3MxFu5O/FkK3kQIfw1W1lBVZCyw7dpYIiJAMU8UtJ2DwM0WWgfBdiuCMLs8JihZIwWkZ/58eanrl0uBCFKE55CN2Vd5cARQ1SD1YKtwgWvE7R+EDk6RXxJ6UtYynA7Tcabji0PREbdq6q+HU8xZ+SnKAexPUsnB7BuVysN5OkkUep6ZmkGdzMK/3Fc211kuWVO0i0X2XDN7f5mEvR5gj5jRTn4zznXNScUAwmOUL9zxoR9MiMOICYfD9PrMYOpNjkbAFO2tzFLMNGme7FjH9gTrdjDdpFB/6l/aK30t5gDZgAACDj7O1/6x9KhMAJV/RwZx8QfVx85NNVpRoIc9OdLGIG8cZ7ksbc9c+YWZbjbz6GXZwbmcqGdLKeEBJZADqTFYHoOEaZ0ALSC32GSfuP+ygLqKcoJ+mXKrjkXHmjJ8ir7ySj4SQVudfx6eS6/KOCfHVlQ0Zlzl1pXzNq11f35ENJ5HhT0cX7DDDWJGQnFqIPhUUGqbj2RZLku3YA4EBsawMd7DnMC5Fp/9+VGHl6rPKzysUpS3bKRp4rQw0qFiBLHk3WkenAQbb4B8PKRETHc/ZvrU7/aWv3nzFJBOoCy2of/ahuSfmC6J1nSoRC704mxSRYn5Yt6LcimqB3rGJBaUGX2JM1evVTuCafiOO7UeE2GeuZOs2hEDo3oNcJb4ncMDKgi6xaG2fo6oMtQ56PlODzlJC66VgS29nyg1QfACs4i1SxG3hHmmB0ujHBdgDdgO/w5x0WWXljqpF5ivxlgyuFyu3/k8tatPgZ2zGG6bH3Ma48QpwLqnzPiXlGhFQKDr5E1aZMXRKvv7jt8xbyj9rrwlp2ia3oHuUqkyuSfZPWw35WJTm4nD7mqmZwVJCC9drx3aj2VyiBjMtMxkrPHYw8fJwcNJ1Pc3hPE0Sa9h5bRHBJl3ZMTmXi7xpBpRuvmgC2bwLhrsdPop3fiKAeTui82J80SlcAlMI3gLBWu2PNEI4mzzYnj1FXMEjB33IN3/tUAC4L93aMHDIB05Cls+7KebNpZhMZZzg1dUxvY7m+x5bO7Rim3hHAea2sC)
获取accessToken步骤
1.访问Azure创建应用Microsoft Azure,使用微软账号进行登录即可!
2.进入应用创建密码
3.获取code
通过访问(必须用浏览器,通过地址栏输入的方式):https://login.live.com/oauth20_authorize.srf?client_id=你的应用程序(客户端) ID&scope=files.readwrite offline_access&response_type=code&redirect_uri=http://localhost:8080/redirectUri
以上步骤都正确的情况下,会在地址栏返回一个code,也就是M.C105.........
4.获取accessToken
拿到code后就可以拿token了,通过对https://login.live.com/oauth20_token.srf 发起POST请求并传递相关参数,这一步需要用接口调试工具完成!
其中client_id和redirect_uri与上面相同,client_secret填刚刚创建的密钥,code就是刚刚获取到的code,grant_type就填authorization_code即可!
正常情况下访问后就能得到access_token,然后把access_token放在springboot的配置文件中!
代码实现步骤
1. 新建一个springBoot项目,选择web依赖即可!
2. 引入相关依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.0</version>
</dependency>
3.编写文件上传接口类
参考文档:上传小文件 - OneDrive API - OneDrive dev center | Microsoft Learn
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/**
* 文件上传到OneDrive并将文件信息存储到Excel文件中
*/
@Controller
public class FileSyncController {
private static final Logger logger = LoggerFactory.getLogger(FileSyncController.class);
private static final String ONE_DRIVE_BASE_URL = "https://graph.microsoft.com/v1.0/me/drive/root:/uploadfile/";
@Value("${onedrive.access-token}")
private String ACCESS_TOKEN;
@PostMapping("/upload")
public void uploadFileToDrive(@RequestParam("file") MultipartFile file, HttpServletResponse httpServletResponse) throws IOException {
if (file.isEmpty()) {
throw new RuntimeException("文件为空!");
}
String fileName = file.getOriginalFilename();
String oneDriveUploadUrl = ONE_DRIVE_BASE_URL + fileName + ":/content";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.setBearerAuth(ACCESS_TOKEN);
HttpEntity<byte[]> requestEntity;
try {
byte[] fileBytes = file.getBytes();
requestEntity = new HttpEntity<>(fileBytes, headers);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(oneDriveUploadUrl, HttpMethod.PUT, requestEntity, String.class);
if (response.getStatusCode() == HttpStatus.CREATED) {
//解析返回的JSON字符串,获取文件路径
String downloadUrl = JSONObject.parseObject(response.getBody()).getString("@microsoft.graph.downloadUrl");
storeFileInfoToExcel(fileName, downloadUrl);
logger.info("文件上传成功,OneDrive 文件路径:" + downloadUrl);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType("text/html;charset=utf-8");
PrintWriter out = httpServletResponse.getWriter();
out.print("<script> alert('" + fileName + "已上传成功!');window.location.href='file_info.xlsx';</script>");
} else {
throw new RuntimeException("文件上传失败!");
}
}
/**
* 将文件信息存储到Excel文件中
*
* @param filename 文件名称
* @param filepath 文件路径
*/
private void storeFileInfoToExcel(String filename, String filepath) {
try {
File file = new File(ResourceUtils.getURL("classpath:").getPath() + "/static/file_info.xlsx");
XSSFWorkbook excel;
XSSFSheet sheet;
FileOutputStream out;
// 如果文件存在,则读取已有数据
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
excel = new XSSFWorkbook(fis);
sheet = excel.getSheetAt(0);
fis.close();
} else {
// 如果文件不存在,则创建一个新的工作簿和工作表
excel = new XSSFWorkbook();
sheet = excel.createSheet("file_info");
// 创建表头
XSSFRow headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("文件名称");
headerRow.createCell(1).setCellValue("文件路径");
}
// 获取下一个行号
int rowNum = sheet.getLastRowNum() + 1;
// 创建新行
XSSFRow newRow = sheet.createRow(rowNum);
newRow.createCell(0).setCellValue(filename);
newRow.createCell(1).setCellValue(filepath);
// 将数据写入到文件
out = new FileOutputStream(file);
excel.write(out);
// 关闭资源
out.close();
excel.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
4.编写认证回调接口类
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RedirectController {
/**
* 回调地址
* http://localhost:8080/redirectUri?code=M.C105_BL2.2.127d6530-7077-3bcd-081e-49be3abc3b45
*
* @param code
* @return
*/
@GetMapping("/redirectUri")
public String redirectUri(String code) {
return code;
}
}
5.编写application.properties配置文件
# 应用服务 WEB 访问端口
server.port=8080
#OneDrive的ACCESS_TOKEN
onedrive.access-token=你的ACCESS_TOKEN
6.编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OneDriveUploadApplication {
public static void main(String[] args) {
SpringApplication.run(OneDriveUploadApplication.class, args);
}
}
7.编写上传页面,放在resources的static目录中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<div align="center">
<h1>文件上传</h1>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file"><br><br>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>