1.通过机器码获取token

1.1.通过devicecode接口获取机器码

  1. url:https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode
  2. scope:user.read offline_access openid profile email
  3. //client_id是应用程序的ID
  4. client_id:86a9b7b0-90f5-40dd-9496-008e96a1fcd0
  5. method:post

image.png

1.2.账号密码登录microsoft应用

通过1.1章节接口返回的message参数通过机器码登录应用
image.png

1.3.首次获取激活机器码的token

  1. url:https://login.microsoftonline.com/winhanverky.onmicrosoft.com/oauth2/v2.0/token
  2. grant_type:urn:ietf:params:oauth:grant-type:device_code
  3. //client_id是应用程序的ID
  4. client_id:86a9b7b0-90f5-40dd-9496-008e96a1fcd0
  5. //1.1章返回参数的device_code值
  6. code:HAQABAAEAAAD--DLA3VO7QrddgJg7WevrDVpBdib5OSWJxTiYZAdx...
  7. method:post

image.png

1.4.刷新令牌

  1. url:https://login.microsoftonline.com/winhanverky.onmicrosoft.com/oauth2/v2.0/token
  2. grant_type:refresh_token
  3. scope:Files.ReadWrite.All
  4. //client_id是应用程序的ID
  5. client_id:86a9b7b0-90f5-40dd-9496-008e96a1fcd0
  6. //1.3章节的refresh_token
  7. refresh_token:0.AVUAcIidqvvpS0eQsil_14h0hLC3qYb1kN1AlJYAjpah_NBVAPk....
  8. method:post

image.png

2.获取文件夹下所有的文件

运行地址:https://developer.microsoft.com/zh-cn/graph/graph-explorer

//Allocation Report为根目录下文件夹名
url:https://graph.microsoft.com/v1.0/me/drive/root:/Allocation Report:/children/

//1.4章返回的access_token参数
Authorization:eyJ0eXAiOiJKV1QiLCJub25jZSI6InNOU016UTZHTG...

Accept:application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8

Content-Type:application/x-www-form-urlencoded

method:get

image.png
image.png

3.上传文本文件

//Allocation Report是目录名称,maxtest.txt是文件名称
url:https://graph.microsoft.com/v1.0/me/drive/root:/Allocation Report/maxtest.txt:/content

//1.4章返回的access_token参数
Authorization:eyJ0eXAiOiJKV1QiLCJub25jZSI6InNOU016UTZHTG...

Content-Type:text/plain

method:put

image.png
image.png
image.png

4.大文件上传

4.1.创建上传会话

//01MHLK4CE2F27NJRUVPVF2Y4ZTXETF3DAX是文件夹的ID
url:https://graph.microsoft.com/v1.0/me/drive/items/01MHLK4CE2F27NJRUVPVF2Y4ZTXETF3DAX/createUploadSession

//1.4章返回的access_token参数
Authorization:eyJ0eXAiOiJKV1QiLCJub25jZSI6InNOU016UTZHTG...

Content-Type:application/json

method:post

body:
    {
    "item": {
        "@microsoft.graph.conflictBehavior": "rename"
    },
    "deferCommit": true,
    "name": "filename1.txt"
}

image.png
image.png

5.创建工具类

其中DictUtils是字典工具类,在这里的作用是获取和保存字典内容

package com.jeeplus.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ibm.icu.text.SimpleDateFormat;
import com.jeeplus.common.utils.net.HttpUtil;
import com.jeeplus.modules.api.entity.OneDriverFile;
import com.jeeplus.modules.sys.entity.DictValue;
import com.jeeplus.modules.sys.service.DictTypeService;
import com.jeeplus.modules.sys.utils.DictUtils;
import okhttp3.*;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author Max Teng
 * @version 2021-11-05 10:56
 * OneDriver工具类
 **/
public class OneDriverUtils {

    private static final String MICROSOFT_ONE_DRIVER_REFRESH_TOKEN_URL = "https://login.microsoftonline.com/winhanverky.onmicrosoft.com/oauth2/v2.0/token";
    private static final String MICROSOFT_ONE_DRIVER_FILE_FOLDER_URL ="https://graph.microsoft.com/v1.0/me/drive/root:/{item-path}:/children/";
    private static final String MICROSOFT_ONE_DRIVER_ITEMS_URL ="https://graph.microsoft.com/v1.0/me/drive/root/children";
    private static final String MICROSOFT_ONE_DRIVER_FILE_FOLDER ="Allocation Report";
    private static final String MICROSOFT_ONE_DRIVER_CREATE_UPLOAD_SESSION_URL = "https://graph.microsoft.com/v1.0/me/drive/root:/{item-path}:/createUploadSession";

    public static final String CONTENT_TYPE_TXT = "text/plain";
    public static final String CONTENT_TYPE_CSV = "text/csv";
    public static final String CONTENT_TYPE_XLSX = "text/xlsx";
    public static final String CONTENT_TYPE_XLS = "application/vnd.ms-excel";
    public static final String CONTENT_TYPE_PNG = "image/png";
    public static final String CONTENT_TYPE_ZIP = "application/zip";
    public static final String CONTENT_TYPE_JSON = "application/json";
    public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";

    @Autowired
    private static DictTypeService dictTypeService;

    /**
     * 获取访问令牌
     * @return string
     */
    public static String getAccessToken(){
        return OneDriverUtils.refreshToken();
    }

    /**
     * 刷新OneDriver的令牌
     * @return accessToken
     */
    public static String refreshToken(){
        try {
            Map<String,String> params = new HashMap<>();
            params.put("refresh_token", URLEncoder.encode(OneDriverUtils.getOneDriverSysConfig("onedriver_refresh_token"),"utf-8"));
            params.put("client_id",URLEncoder.encode(OneDriverUtils.getOneDriverSysConfig("onedriver_client_id"),"utf-8"));
            params.put("scope",URLEncoder.encode("Files.ReadWrite.All","utf-8"));
            params.put("grant_type","refresh_token");
            String bufferStr = HttpUtil.post(MICROSOFT_ONE_DRIVER_REFRESH_TOKEN_URL,params,new HashMap<>());
            JSONObject jsonObject = JSONObject.parseObject(bufferStr);
            OneDriverUtils.updateOneDriverSysConfig(jsonObject.get("refresh_token").toString(),"onedriver_refresh_token");
            OneDriverUtils.updateOneDriverSysConfig(jsonObject.get("access_token").toString(),"onedriver_access_token");
            return jsonObject.get("access_token").toString();
        } catch (Exception e){
            e.printStackTrace();
        }
        return OneDriverUtils.getOneDriverSysConfig("onedriver_access_token");
    }
    /**
     * 获取默认文件夹名称下的所有子项
     * @return List<OneDriverFile>
     */
    public static List<OneDriverFile> getFileFolderChildren(){
        return OneDriverUtils.getFileFolderChildren(MICROSOFT_ONE_DRIVER_FILE_FOLDER);
    }

    /**
     * 获取文件夹名称下的所有子项
     * @param folderName 文件夹名称
     * @return List<OneDriverFile>
     */
    public static List<OneDriverFile> getFileFolderChildren(String folderName){
        List<OneDriverFile> list = new ArrayList<>();
        if(StringUtils.isNotBlank(folderName)){
            try {
                String url = MICROSOFT_ONE_DRIVER_FILE_FOLDER_URL.replace("{item-path}",folderName);
                Map<String,String> headers = new HashMap<>();
                headers.put("Authorization",OneDriverUtils.getAccessToken());
                headers.put("Accept","application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8");
                headers.put("Content-Type", CONTENT_TYPE_FORM);
                String bufferStr = HttpUtil.get(url,null,headers);
                List<Map<String, Object>> fileList = (List<Map<String, Object>>) JSONArray.parse(JSON.parseObject(bufferStr).getString("value"));
                for(Map<String, Object> file : fileList){
                    file.put("filePath",url);
                    list.add(new OneDriverFile(file));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    /**
     * 获取OneDriver sys_config系统配置
     * @param label
     * @return
     */
    public static String getOneDriverSysConfig(String label){
        return DictUtils.getDictValue(label,"sys_config","");
    }
    /**
     * OneDriver sys_config系统配置
     * @param token OneDriver令牌
     * @param label access_token|refresh_token
     */
    public static void updateOneDriverSysConfig(String token,String label){
        DictValue d = DictUtils.getDictValue(label,"sys_config");
        if(null != d){
            d.setValue(token);
            dictTypeService.saveDictValue(d);
            DictUtils.clearCache();
        }
    }
    /**
     * 默认文件夹上传文件
     * @param fileName 文件名称
     * @param multipartFile 文件
     * @throws Exception
     * @return 应答内容
     */
    public static String uploadFile(String fileName, MultipartFile multipartFile) throws Exception {
        return OneDriverUtils.uploadFile(fileName,CONTENT_TYPE_XLSX, multipartFile);
    }
    /**
     * 默认文件夹上传自定义文件
     * @param fileName 文件名称
     * @param multipartFile 文件
     * @param putUploadMediaType 上传文件类型
     * @throws Exception
     * @return 应答内容
     */
    public static String uploadFile(String fileName,String putUploadMediaType, MultipartFile multipartFile) throws Exception {
        return OneDriverUtils.uploadFile(MICROSOFT_ONE_DRIVER_FILE_FOLDER,fileName,putUploadMediaType, multipartFile);
    }

    /**
     * 自定义文件夹上传文件
     * @param folderName 文件夹名称
     * @param fileName 文件名称
     * @param multipartFile 文件
     * @param putUploadMediaType 上传文件类型
     * @throws Exception
     * @return 应答内容
     */
    public static String uploadFile(String folderName, String fileName,String putUploadMediaType, MultipartFile multipartFile) {
        String message = null;
        try {
            String url  = MICROSOFT_ONE_DRIVER_CREATE_UPLOAD_SESSION_URL.replace("{item-path}",folderName+"/"+fileName);
            JSONObject params = new JSONObject();
            JSONObject item = new JSONObject();
            item.put("@microsoft.graph.conflictBehavior","rename");
            params.put("item",item);
            params.put("name",fileName);

            if(null == multipartFile){
                throw new RuntimeException("上传文件异常");
            }
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .build();
            MediaType mediaType = MediaType.parse(CONTENT_TYPE_JSON);
            RequestBody body = RequestBody.create(mediaType, params.toJSONString());
            Request request = new Request.Builder()
                    .url(url)
                    .method("POST", body)
                    .addHeader("Authorization", OneDriverUtils.getAccessToken())
                    .addHeader("Content-Type", CONTENT_TYPE_JSON)
                    .build();
            Response response = client.newCall(request).execute();
            JSONObject jsonObject = JSONObject.parseObject(response.body().string());
            String uploadUrl = jsonObject.get("uploadUrl").toString();
            if(StringUtils.isNotBlank(uploadUrl)){
                OkHttpClient uploadClient = new OkHttpClient().newBuilder().build();
                MediaType uploadMediaType = MediaType.parse(putUploadMediaType);
                RequestBody uploadBody = RequestBody.create(uploadMediaType, multipartFile.getBytes());
                int fileSize = multipartFile.getBytes().length;
                Request uploadRequest = new Request.Builder()
                        .url(uploadUrl)
                        .method("PUT", uploadBody)
                        .addHeader("Content-Length", String.valueOf(fileSize))
                        .addHeader("Content-Range", "bytes 0-"+(fileSize-1)+"/"+fileSize)
                        .addHeader("Content-Type", putUploadMediaType)
                        .build();
                Response uploadResponse = uploadClient.newCall(uploadRequest).execute();
                message =  uploadResponse.body().string();
            }
        } catch (Exception e) {
            e.printStackTrace();
            message = e.getMessage();
        }
        return message;
    }
    /**
     * 上传文本文件
     * @param folderName 根目录文本夹名称
     * @param fileName 文件名称
     * @param content 文本内容
     * @throws IOException
     */
    public static void uploadTxtFile(String folderName,String fileName,String content) throws IOException{
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String url = MICROSOFT_ONE_DRIVER_FILE_FOLDER_URL.replace("{item-path}",folderName);
        url = url.replace(":/children","/"+fileName+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+".txt:/content");
        url = url.replace(" ", "%20");
        HttpPut put = new HttpPut(url);
        put.setEntity(new StringEntity(content));
        put.addHeader("Authorization", OneDriverUtils.getAccessToken());//获取访问OneDriver 接口的令牌token
        put.addHeader(HTTP.CONTENT_TYPE, CONTENT_TYPE_TXT);
        HttpResponse httpResponse = httpclient.execute(put);
    }
}