业务需求介绍:
用户会在SharePoint具体站点创建分类文件,开发人员需要在不同文件夹下获取文件并实现上传。
前置条件:具体的站点需要有权限的用户名密码授权访问。
一、SharePoint介绍
精心规划和执行的信息体系结构是智能和高性能 Intranet、中心或网站的先决条件。
规划有效信息体系结构最重要的第一步是了解用户,并帮助他们找到以对他们最有意义的方式完成任务所需的内容。信息体系结构还有助于提高用户采用率、满意度和工作效率,同时降低 IT 成本,减少信息过载,并最大程度地降低合规性和安全风险。
官网介绍:https://learn.microsoft.com/zh-cn/sharepoint/information-architecture-modern-experience
二、获取文件数据
1. yml配置
sharepoint:
auth:
username: 授权了的用户账号
password: 用户账号密码
siteUrl: 服务器URL
domain: 域地址
2. 配置类兼工具类
定义授权 getAuthenticatedResponse 方法,根据具体情况获取FormDigestValue
@ConfigurationProperties(prefix = "sharepoint.auth")
@Getter
@Setter
@Configuration
public class SharePointUtils {
private String username;
private String password;
private String siteUrl;
private String domain;
// 授权
public String getAuthenticatedResponse(final String urlStr, final String domain, final String userName, final String password) throws IOException {
StringBuffer response = new StringBuffer();
Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(domain + "\\" + userName, password.toCharArray());
}
});
URL urlRequest = new URL(urlStr + "/_api/contextinfo");
//获取contextinfo
HttpURLConnection contextInfoRequest = (HttpURLConnection) urlRequest.openConnection();
contextInfoRequest.setRequestProperty("Content-Type", "application/json;odata=verbose");
contextInfoRequest.setRequestProperty("Accept", "application/json;odata=verbose");
contextInfoRequest.setRequestProperty("Connection", "Keep-Alive");
contextInfoRequest.setDoOutput(true);
contextInfoRequest.setDoInput(true);
contextInfoRequest.setRequestMethod("POST");
contextInfoRequest.connect();
OutputStream out = contextInfoRequest.getOutputStream();
out.flush();
InputStream in = contextInfoRequest.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String str = "";
while ((str = br.readLine()) != null) {
response.append(str);
}
String returnValue = new String(response);
Map jobj = JSONUtil.toBean(returnValue, Map.class);
//获取第一层
Map A1 = (Map) jobj.get("d");
//System.err.println("A1:"+A1);
//获取第二层
Map A2 = (Map) A1.get("GetContextWebInformation");
//System.err.println("A2:"+A2);
//获取第三层
Object A3 = A2.get("FormDigestValue");
System.err.println("A3:" + A3.toString());
out.close();
in.close();
return A3.toString();
}
}
这里对其做出介绍:
为什么需要这个FormDigestValue?
在SharePoint中进行数据修改时,必须包含FormDigest控件来为安全验证创建digest。它主要基于当前的用户、站点和时间在页面中添加一个安全标示(security token),一旦页面post back回到SharePoint Server上,这个安全标示会被验证。
这个安全标示一旦创建出来,它只在一个可设置的时间段是有效的。由于安全问题,Microsoft SharePoint Foundation不允许从一个Web application往回Post数据来修改存储在数据库中的数据,除非在发送这个Post请求时在页面中包含了安全验证。
大白话:类似于token,这个就是鉴权的
这里的大致长这个样子:A3:
0x569F150668434DF0D75463ED8421570D2256F14632892CD77D878ECE89E37BF46A9A685627EF432B734750EE9CB62C8A45CEBF96BF589EF59F7C4A……,24 Oct 2023 02:29:03 -0000
3. 获取具体文件下数据
该业务场景为获取具体流程对应活动下的模板数据,所以文件夹只有两层,具体情况做相应调整。
public List<SharePointResultDTO> getTemplateData(String process, String activity) {
HttpURLConnection connection = null;
try {
String apiUrl;
if (StringUtils.isNotEmpty(process) && StringUtils.isNotEmpty(activity)) {
apiUrl = siteUrl + "/_api/web/GetFolderByServerRelativeUrl('[相应的站点地址,如果有中文需要进行统一编码,否则会报错]" + URLEncoder.encode(process, "UTF-8") + "/" + URLEncoder.encode(activity, "UTF-8") + "')/files";
} else {
apiUrl = siteUrl + "/_api/web/GetFolderByServerRelativeUrl('[相应的站点地址,如果有中文需要进行统一编码,否则会报错]')/files";
}
URL url = new URL(apiUrl);
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json;odata=verbose");//请求头中设置ContentType对应值
connection.setRequestProperty("Accept", "application/json;odata=verbose");//请求头中设置Accept对应值
connection.setRequestProperty("X-RequestDigest", getAuthenticatedResponse(siteUrl, domain, username, password));
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("GET");
Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(domain + "\\" + username, password.toCharArray());
}
});
connection.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
if (StringUtils.isNotEmpty(response)) {
ArrayList<SharePointResultDTO> sharePointResultDTOS = new ArrayList<>();
//对获取到的数据进行相应的解析 …………
return sharePointResultDTOS;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
若出现数据为空或者出现 "Unable to excute HTTP request: Permission denied: connect"等错误,可能是网络原因,浏览器尝试通过对应账号密码访问到对应的目录文件下然后再尝试。
4. 结果展示
三、上传文件
1. 获取文件字节流
/**
* 获取本地文件,将文件转为byte[]
*/
public static byte[] getBytes(String filePath) throws IOException {
File file = new File(filePath);
FileInputStream fis = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
try {
fis = new FileInputStream(file);
//创建个字节数组,给定长度为1000
byte[] byteArr = new byte[1000];
int n;
//进行循环读取文件内容,当read返回值为-1的时候,表示文件读取完毕,就可以显示文件内容
//读取到的字节全部放入到指定的字节数组byteArr 返回每次填充给bytes数组的长度
while ((n = fis.read(byteArr)) != -1) {
//将指定的字节数组写入文件
bos.write(byteArr, 0, n);
}
return bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
fis.close();
}
bos.close();
}
return null;
}
//获取链接地址文件的byte数据
public byte[] getUrlFileData(String fileUrl) throws Exception {
// 文件做相应处理,获取可以下载到的文件链接,有中文需要进行编码处理
// ……
URL url = new URL(fileUrl);
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json;odata=verbose");//请求头中设置ContentType对应值
connection.setRequestProperty("Accept", "application/json;odata=verbose");//请求头中设置Accept对应值
connection.setRequestProperty("X-RequestDigest", getAuthenticatedResponse(siteUrl, domain, username, password));
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("GET");
Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(domain + "\\" + username, password.toCharArray());
}
});
connection.connect();
InputStream cin = connection.getInputStream();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int len = 0;
while ((len = cin.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
byte[] fileData = outStream.toByteArray();
cin.close();
outStream.close();
return fileData;
}
2. 上传文件
public SharePointResultDTO postFileByRestful(byte[] buffer, String fileName) {
HttpURLConnection connection = null;
BufferedReader reader = null;
InputStream is = null;
OutputStream out = null;
try {
StringBuffer sbf = new StringBuffer();
String strRead = null;
String allurl = siteUrl + "/_api/web/GetFolderByServerRelativeUrl('[相应的站点地址,如果有中文需要进行统一编码,否则会报错]')/files/add(url='" + URLEncoder.encode(fileName, "UTF-8") + "',overwrite=true)";
URL url = new URL(allurl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json;odata=verbose");//请求头中设置ContentType对应值
connection.setRequestProperty("Accept", "application/json;odata=verbose");//请求头中设置Accept对应值
connection.setRequestProperty("Content-Length", String.valueOf(buffer.length));//请求中携带参数的长度
connection.setRequestProperty("X-RequestDigest", getAuthenticatedResponse(siteUrl, domain, username, password));
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(domain + "\\" + username, password.toCharArray());
}
});
connection.connect();
out = connection.getOutputStream();
out.write(buffer, 0, buffer.length);
out.flush();
connection.setInstanceFollowRedirects(false);
is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
}
reader.close();
is.close();
out.close();
connection.disconnect();
// 将获取数据进行json解析,封装自己需要返回的数据 …………
return sharePointResultDTO;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
3. 结果展示
写在最后:今天是1024,祝大家和自己程序员节日快乐,一起进步一起变好!