java - Sharepoint 使用 JAVA 批量上传
问题描述
我有一个现有的 API 到 SharePoint API 的单一列表。新要求是使用相同的 API 上传多个数据。我们正在使用 NTLM 身份验证访问。在同一代码中,当我尝试传递多个项目时,它仍然保存唯一的第一个项目。我已经通过多个帖子解决了这个问题,但无法解决其中一个是批量上传共享点,我尝试了这个,但这里的身份验证不同,请建议我如何在我的代码中实现这一点。
以下是上传 1 个列表项的代码。
public class RESTApiUtil {
public static void main(String[] args) throws Exception {
String jsonInputString = "{ \"__metadata\": { \"type\": \"SP.Data.Raffle_x005f_Draw_x005f_RegistrationListItem\" },"
+ "\"Title\": \"title1\",\"Employee_Email\": \"employee1@gmail.com\","
+ "\"Employee_Name\": \"empName\",\"Registration_Date\": \"12-06-2019\",\"Employee_No\": \"123\"},"+
"{ \"__metadata\": { \"type\": \"SP.Data.Raffle_x005f_Draw_x005f_RegistrationListItem\" },"
+ "\"Title\": \"title2\",\"Employee_Email\": \"employee2@gmail.com\","
+ "\"Employee_Name\": \"empName2\",\"Registration_Date\": \"12-06-2019\",\"Employee_No\": \"1234\"}";
System.out.println(callPostAPI(
"http://host/_api/contextinfo",
"http://host/_api/web/lists/getbytitle('Registration')/items",
"userName", "password",
"domain",jsonInputString));
}
public static String callPostAPI(String digestUrl, String postApiUrl, final String userName, final String password,
final String domain, String postBody) {
StringBuffer response = new StringBuffer();
try {
String requestDigest = getRequestDigest(digestUrl, postApiUrl, userName, password, domain,"");
String cookie = getCookieValue(postApiUrl, userName, password, domain, requestDigest, "");
if(cookie!=null&&!"".equals(cookie)) {
requestDigest = getRequestDigest(digestUrl, postApiUrl, userName, password, domain,cookie);
if (requestDigest != null && !"".equals(requestDigest)) {
response.append(sendPostRequest(postApiUrl, userName, password, domain, requestDigest, postBody));
} else {
response.append("Failed To Get Request Digest");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response.toString();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static String getRequestDigest(String urlStr,String postApiUrl, final String userName, final String password, final String domain,String cookie) {
String response = "";
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
int port = 80;
String serverName = "";
int endIndex = 0;
int index = urlStr.indexOf("/");
int count=0;
while(index >= 0) {
count++;
index = urlStr.indexOf("/", index+1);
if(count==2) {
endIndex = index;
break;
}
}
String splitedServerName = urlStr.substring(urlStr.indexOf("//")+2,endIndex);
serverName = splitedServerName;
if(splitedServerName.contains(":")) {
serverName = splitedServerName.split(":")[0];
port = Integer.valueOf(splitedServerName.split(":")[1]);
}
NTCredentials creds = new NTCredentials(userName, password, domain, domain);
httpclient.getCredentialsProvider().setCredentials(new AuthScope(serverName, port), creds);
List authpref = new ArrayList();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref);
HttpHost target = new HttpHost(serverName, port, "http");
HttpPost httpPost = new HttpPost(urlStr);
httpPost.setHeader("Accept", "application/json;odata=verbose");
httpPost.setHeader("Content-Type", "application/json;odata=verbose");
if(!"".equals(cookie))
httpPost.setHeader("Cookie", cookie);
HttpContext localContext = new BasicHttpContext();
HttpResponse response1 = httpclient.execute(target,httpPost, localContext);
StringBuilder output = new StringBuilder();
InputStream stream = response1.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
output.append(str);
}
in.close();
JSONObject obj = new JSONObject(output.toString());
JSONObject obj1 = obj.getJSONObject("d");
JSONObject obj2 = obj1.getJSONObject("GetContextWebInformation");
response = obj2.getString("FormDigestValue");
return response;
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
private static String sendPostRequest(String postUrl, String userName, String password, String domain, String digest,
String postBody) throws IOException {
String response = "";
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
int port = 80;
String serverName = "";
int endIndex = 0;
int index = postUrl.indexOf("/");
int count=0;
while(index >= 0) {
count++;
index = postUrl.indexOf("/", index+1);
if(count==2) {
endIndex = index;
break;
}
}
String splitedServerName = postUrl.substring(postUrl.indexOf("//")+2,endIndex);
serverName = splitedServerName;
if(splitedServerName.contains(":")) {
serverName = splitedServerName.split(":")[0];
port = Integer.valueOf(splitedServerName.split(":")[1]);
}
NTCredentials creds = new NTCredentials(userName, password, domain, domain);
httpclient.getCredentialsProvider().setCredentials(new AuthScope(serverName, port), creds);
List authpref = new ArrayList();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref);
HttpHost target = new HttpHost(serverName, port, "http");
HttpPost httpPost = new HttpPost(postUrl);
httpPost.setHeader("Accept", "application/json;odata=verbose");
httpPost.setHeader("Content-Type", "application/json;odata=verbose");
httpPost.setHeader("X-RequestDigest", digest);
System.out.println("postbody "+postBody);
//Jar file: json-simple-1.1.1.jar
/* String[] data= postBody.split("},");
for(int i=0;i<data.length;i++) {
String str=data[i].toString();
System.out.println("Struing "+str);
}*/
StringEntity params =new StringEntity(postBody);
httpPost.setEntity(params);
HttpContext localContext = new BasicHttpContext();
HttpResponse response1 = httpclient.execute(target,httpPost, localContext);
StringBuilder output = new StringBuilder();
InputStream stream = response1.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String str = "";
while ((str = in.readLine()) != null) {
output.append(str);
}
return output.toString();
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
private static String getCookieValue(String postUrl, String userName, String password, String domain, String digest,
String postBody) throws IOException {
String response = "";
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
int port = 80;
String serverName = "";
int endIndex = 0;
int index = postUrl.indexOf("/");
int count=0;
while(index >= 0) {
count++;
index = postUrl.indexOf("/", index+1);
if(count==2) {
endIndex = index;
break;
}
}
String splitedServerName = postUrl.substring(postUrl.indexOf("//")+2,endIndex);
serverName = splitedServerName;
if(splitedServerName.contains(":")) {
serverName = splitedServerName.split(":")[0];
port = Integer.valueOf(splitedServerName.split(":")[1]);
}
NTCredentials creds = new NTCredentials(userName, password, domain, domain);
httpclient.getCredentialsProvider().setCredentials(new AuthScope(serverName, port), creds);
List authpref = new ArrayList();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref);
HttpHost target = new HttpHost(serverName, port, "http");
HttpPost httpPost = new HttpPost(postUrl);
httpPost.setHeader("Accept", "application/json;odata=verbose");
httpPost.setHeader("Content-Type", "application/json;odata=verbose");
httpPost.setHeader("X-RequestDigest", digest);
StringEntity params =new StringEntity(postBody);
httpPost.setEntity(params);
HttpContext localContext = new BasicHttpContext();
HttpResponse response1 = httpclient.execute(target,httpPost, localContext);
Header[] headers = response1.getAllHeaders();
for (Header header: headers) {
if(header.getName()!=null) {
if("Set-Cookie".equals(header.getName())) {
response = header.getValue().substring(0, header.getValue().indexOf(";"));
if(response.contains("WSS_KeepSessionAuthenticated"))
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
}
更新
我已经更新了我根据帖子创建批处理数据的代码,并尝试在 setEntity() 方法中传递它。
StringEntity params =new StringEntity(getData(postBody,postUrl));
httpPost.setEntity(params);
private static String getData(String postBody, String postUrl) {
//generate uniqueId for a batch boundary
String batchGuid = generateUUID();
//generate uniqueId for each item to be inserted
String changeSetId = generateUUID();
//Begin of: Prepare Bulk Request Format for SharePoint Bulk-Insert-Query ----------------
String batchContents = "";
try {
//Parse the output-count JSON
JSONObject obj = new JSONObject(postBody);
String[] data= JSONObject.getNames(obj);
JSONArray jsonArr = obj.toJSONArray(new JSONArray(data)); //Returned string in JSonArray, so convert it to JSonArray
//SharePoint URL to insert one item
String endpoint_Insert = postUrl;
//Start: changeset to insert data ----------
String batchCnt_Insert = "";
for(int i=0; i<jsonArr.length(); i++){
JSONObject jsonObj = new JSONObject();
jsonObj = (JSONObject) jsonArr.get(i); //get ith array object
String title = (jsonObj.get("tytle")).toString();
String employeeEmail = (jsonObj.get("employeEmail")).toString();
String employeeName= (jsonObj.get("employeeName")).toString();
String employeeNo= (jsonObj.get("employeeNo")).toString();
String registrationDate =(jsonObj.get("registrationDate")).toString();
//Start:create INSERT-Statement for one Item ---------------------------
String request = "{ \"__metadata\": { \"type\": \"SP.Data.Raffle_x005f_Draw_x005f_RegistrationListItem\" },"
+ "\"Title\": \""+title+"\",\"Employee_Email\": \""+employeeEmail+"\","
+ "\"Employee_Name\": \""+employeeName+"\",\"Registration_Date\": \""+registrationDate+"\",\"Employee_No\": \""+employeeNo+"\"}";
batchCnt_Insert = batchCnt_Insert
+ "--changeset_" + changeSetId + "\n"
+ "Content-Type: application/http" + "\n"
+ "Content-Transfer-Encoding: binary" + "\n"
+ "" + "\n"
+ "POST " + endpoint_Insert + " \n"
+ "Content-Type: application/json;odata=verbose" + "\n"
+ "" + "\n"
+ request + "\n"
+ "" + "\n";
//END:create INSERT-Statement for one Item ------------------------------
}
//END: changeset to insert data ----------
batchCnt_Insert = batchCnt_Insert + "--changeset_" + changeSetId + "--\n";
//create batch for creating items
batchContents = "--batch_" + batchGuid + "\n"
+ "Content-Type: multipart/mixed; boundary=\"changeset_" + changeSetId + "\"\n"
+ "Content-Length: " + batchCnt_Insert.length() + "\n"
+ "Content-Transfer-Encoding: binary" + "\n"
+ "" + "\n"
+ batchCnt_Insert + "\n";
}catch (Exception e) {
// TODO: handle exception
}
return batchContents;
}
private static String generateUUID(){
//Generates a GUID-like string, used in HTTP batches
//Generating unique IDs | The identifiers generated by UUID are actually universally unique identifiers.
UUID idOne = UUID.randomUUID();
String idOne_Str = String.valueOf(idOne);
return idOne_Str;
}
我收到以下错误。
postbody {"__metadata": { "type": "SP.Data.RegistrationListItem" },"Title": "New title","Name": "test@gmail.com","Email": "test"},{"__metadata": { "type": "SP.Data.RegistrationListItem" },"Title": "New title","Name": "test@gmail.com","Email": "test"}
{"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"A node of type 'EndOfInput' was read from the JSON reader when trying to read the start of an entry. A 'StartObject' node was expected."}}}
解决方案
在您的代码中,您没有以 Sharepoint REST API 要求的格式发布数据。
预期格式 -
--batch_b27de00f-98f2-4dcb-9fd4-efa8f57380f4 内容类型:多部分/混合;边界="changeset_85050752-ccb7-40d1-a883-2ae3ac0c100c" 内容长度:1161 内容传输编码:二进制
--changeset_85050752-ccb7-40d1-a883-2ae3ac0c100c 内容类型:application/http 内容传输编码:二进制
POST https://ClientDomain.sharepoint.com/teams/SPdev/AlertsCount/_api/web/Lists/GetByTitle ('AlertCount')/Items HTTP/1.1 Content-Type: application/json;odata=verbose
{"__metadata":{"type":"SP.Data.AlertCountListItem"},"Title":"213323","PeningCount":"3"}
--changeset_85050752-ccb7-40d1-a883-2ae3ac0c100c 内容类型:application/http 内容传输编码:二进制
POST https://ClientDomain.sharepoint.com/teams/SPdev/AlertsCount/_api/web/Lists/GetByTitle ('AlertCount')/Items HTTP/1.1 Content-Type: application/json;odata=verbose
{"__metadata":{"type":"SP.Data.AlertCountListItem"},"Title":"231499","PeningCount":"9"}
您发布的代码示例中似乎缺少一些必需的部分 - 例如。您在哪里将 MIME 类型指定为多部分/混合?为什么不在 URL 中使用 $batch 端点?
Sharepoint REST API 具有严格的请求/响应格式,您必须遵守该格式才能使其正常工作。要了解规格,请参阅详细的文档链接。您关注的此链接包含有关如何创建批量插入的示例代码
推荐阅读
- python - Pandas - 在扩展日期窗口中计算组的平均值
- javascript - 事件处理程序中的关闭
- android - 如何在 Android Studio 中使用 VolleyMutlipart 在一个请求中发布多个文件?
- java - 需要在java中打印如下格式的排序地图值
- dll - 如何将更多的 DLL 打包到 tauri 包中?
- javascript - 如何在 LinkedIn 中检索帐户所属的页面和组织
- c++ - C++ 通过 Visual Studio 视频 - “包含在 browse.path 中找不到的文件。” C/C++ [1, 1]
- vue.js - 更改 petite-vue 中的分隔符
- debugging - 调试没有源代码的编译二进制文件
- winforms - 如何进行树搜索?