如何使用 Java 将文档上传到 SharePoint?
Posted
技术标签:
【中文标题】如何使用 Java 将文档上传到 SharePoint?【英文标题】:How do I upload a document to SharePoint with Java? 【发布时间】:2010-09-23 18:38:44 【问题描述】:我正在使用 Java 创建一些大文件(数据库导出),我需要将它们放在我们的 SharePoint 服务器上的某个位置。现在,我正在使用 IE 执行此操作,但我也想自动执行此步骤。
我搜索了网络,发现了一些使用 SOAP 的提示,但我还没有真正了解这一切。有人可以提供一些示例代码或我需要做的食谱吗?
请注意:SharePoint 服务器要求 NT 域身份验证。我什至无法使用 Firefox 登录 :(
编辑
如何将 IE 中可怕的 URL 转换为 WebDAV 路径? 在我用我的代码破坏生产系统之前,是否有可以使用的 WebDAV“浏览器”?我从http://www.davexplorer.org/ 尝试了“DAV Explorer 0.91”,但无法连接(可能是因为 NT 域身份验证)。【问题讨论】:
【参考方案1】:除了Sacha's suggestions,您还可以使用 SharePoint SOAP Web 服务。每个 SharePoint 网站都通过路径 http://<Site>/_vti_bin/
公开一堆 Web 服务。
在您的情况下,您可能需要Lists web service (http://<Site>/_vti_bin/Lists.asmx
)。您可以从http://<Site>/_vti_bin/Lists.asmx?WSDL
获取 WSDL。 WSS 3.0 SDK 详细介绍了如何使用 Web 服务(您可能希望使用 UpdateListItems
和 AddAttachment
方法)。
综上所述,假设您可以解决 NTLM 问题,Sacha 的第一个选项(将文档库映射到驱动器)可能是最简单的方法。
如果您使用的是 Windows,您可以简单地导航到文档库的 UNC 路径。例如,如果您的文档库的浏览器 URL 是:
http://<Site>/Foo/BarDocs/Forms/AllItems.aspx
您只需在 Windows 资源管理器地址栏中键入相应的 UNC 路径:
\\<Site>\Foo\BarDocs
然后将文件拖放到此位置。如果您愿意,可以使用 Windows 资源管理器或 SUBST.EXE 命令行实用程序将此位置映射到驱动器号。
【讨论】:
UNC 不起作用;从什么时候开始?我在 XP 上,但我不知道正在使用哪个版本的 SP。 WSDL 下载有效,但也没有版本信息:/ 我意识到这要晚得多,但 UNC 路径对我有用。我能够使用该路径和 Java 的 IO API 将文档直接写入 Sharepoint。 +1【参考方案2】:好的......经过几个小时的工作并通过微软提供的“文档”以及所有在网络上随机传播的提示,我设法编写了一些示例代码来浏览 SharePoint 服务器的内容:Navigating SharePoint Folders With Axis2.
下一站:上传内容。
【讨论】:
【参考方案3】:另一种解决方案是使用 HTTP PUT 方法将文件直接发送到 Sharepoint。
为此,您可以使用 Apache HTTP 客户端:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.3</version>
</dependency>
并且要允许 NTLMv2 身份验证,您需要 JCIF 库。
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
首先我们需要编写一个包装器以允许 Apache HTTP 客户端使用 JCIF 来支持 NTLMv2:
public final class JCIFSEngine implements NTLMEngine
private static final int TYPE_1_FLAGS =
NtlmFlags.NTLMSSP_NEGOTIATE_56
| NtlmFlags.NTLMSSP_NEGOTIATE_128
| NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2
| NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN
| NtlmFlags.NTLMSSP_REQUEST_TARGET;
@Override
public String generateType1Msg(final String domain, final String workstation)
throws NTLMEngineException
final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
return Base64.encode(type1Message.toByteArray());
@Override
public String generateType3Msg(final String username, final String password,
final String domain, final String workstation, final String challenge)
throws NTLMEngineException
Type2Message type2Message;
try
type2Message = new Type2Message(Base64.decode(challenge));
catch (final IOException exception)
throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
final int type2Flags = type2Message.getFlags();
final int type3Flags = type2Flags
& (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
final Type3Message type3Message = new Type3Message(type2Message, password, domain,
username, workstation, type3Flags);
return Base64.encode(type3Message.toByteArray());
Reference
执行带有身份验证的 HTTP PUT 的主要代码:
try
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
DefaultHttpClient httpclient = new DefaultHttpClient(params);
//Register JCIF NTLMv2 to manage ntlm auth.
httpclient.getAuthSchemes().register("ntlm", new AuthSchemeFactory()
@Override
public AuthScheme newInstance(HttpParams hp)
return new NTLMScheme(new JCIFSEngine());
);
//Provide login/password
httpclient.getCredentialsProvider().setCredentials(
AuthScope.ANY,
new NTCredentials([LOGIN], [PASSWORD], "", [DOMAIN]));
//Create HTTP PUT Request
HttpPut request = new HttpPut("http://[server]/[site]/[folder]/[fileName]");
request.setEntity(new FileEntity([File]));
return httpclient.execute(request);
catch (IOException ex)
//...
【讨论】:
是否可以将此解决方案与 HTTP PUT 和 overwrite=true 一起使用?【参考方案4】:我能想到不同的选择:
将文档库映射到文件驱动器,然后像保存文件系统中的任何其他文件一样保存文件。 使用 HTTP WebDAV 协议。...对于 NTLM 身份验证部分:
http://www.luigidragone.com/networking/ntlm.html
【讨论】:
【参考方案5】:我认为我的方法可能会对您有所帮助。
最初我创建了共享点帐户并按照此链接 (http://www.ktskumar.com/2017/01/access-sharepoint-online-using-postman/) 中的过程获取 REST API 所需的凭据。获得凭据后,我只需要以下依赖项和代码:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
由于我使用了 OAUTH2 身份验证,因此获取访问令牌的代码有助于其他 CRUD 操作。
/* OAuth2 authentication to get access token */
public String getSharePointAccessToken() throws ClientProtocolException, IOException
/* Initializing variables */
String grant_type = RcConstants.GRANT_TYPE;
String client_id = RcConstants.CLIENT_ID;
String client_secret = RcConstants.CLIENT_SECRET;
String resource = RcConstants.RESOURCE;
String url = RcConstants.OAUTH_URL + RcConstants.URL_PARAMETER + "/tokens/OAuth/2";
/*
* NOTE: RcConstants.OAUTH_URL =
* https://accounts.accesscontrol.windows.net/ RcConstants.URL_PARAMETER
* = Bearer Realm from
* (http://www.ktskumar.com/2017/01/access-sharepoint-online-using-
* postman/) Figure 6.
*/
/* Building URL */
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
/* Adding URL Parameters */
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
urlParameters.add(new BasicNameValuePair("grant_type", grant_type));
urlParameters.add(new BasicNameValuePair("client_id", client_id));
urlParameters.add(new BasicNameValuePair("client_secret", client_secret));
urlParameters.add(new BasicNameValuePair("resource", resource));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
/* Executing the post request */
HttpResponse response = client.execute(post);
logger.debug("Response Code : " + response.getStatusLine().getStatusCode());
String json_string = EntityUtils.toString(response.getEntity());
JSONObject temp1 = new JSONObject(json_string);
if (temp1 != null)
/* Returning access token */
return temp1.get("access_token").toString();
return RcConstants.OAUTH_FAIL_MESSAGE;
获得访问令牌后,我们可以使用以下方法上传:
public String putRecordInSharePoint(File file) throws ClientProtocolException, IOException
/* Token variable declaration */
String token = getSharePointAccessToken();
/* Null or fail check */
if (!token.equalsIgnoreCase(RcConstants.OAUTH_FAIL_MESSAGE))
/* Upload path and file name declaration */
String Url_parameter = "Add(url='" + file.getName() + "',overwrite=true)";
String url = RcConstants.UPLOAD_FOLDER_URL + Url_parameter;
/*
* NOTE: RcConstants.UPLOAD_FOLDER_URL =
* https://<your_domain>.sharepoint.com/_api/web/
* GetFolderByServerRelativeUrl('/Shared%20Documents/<FolderName>')/
* Files/
*/
/* Building URL */
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url);
post.setHeader("Authorization", "Bearer " + token);
post.setHeader("accept", "application/json;odata=verbose");
/* Declaring File Entity */
post.setEntity(new FileEntity(file));
/* Executing the post request */
HttpResponse response = client.execute(post);
logger.debug("Response Code : " + response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() == HttpStatus.OK.value()|| response.getStatusLine().getStatusCode() == HttpStatus.ACCEPTED.value())
/* Returning Success Message */
return RcConstants.UPLOAD_SUCCESS_MESSAGE;
else
/* Returning Failure Message */
return RcConstants.UPLOAD_FAIL_MESSAGE;
return token;
【讨论】:
这个签入文件也会上传吗? @MonkeyD.Luffy 在您的共享源代码中什么是 "RcConstants" 。我可以理解它是一个 java 类,你有我猜的所有常量。你能举个例子吗?我们必须在这个常量文件中保留什么。比如常量文件中 "GRANT_TYPE" 、 "RESOURCE" 的值应该是多少?【参考方案6】:使用集成的 Windows 标识,我设法使用此代码将文件下载到共享点,也许它会有所帮助。
public class HttpClient
HttpClient()
public static void download(final String source, final File resultingFile)
CloseableHttpClient client = WinHttpClients.createSystem();
HttpGet httpRequest = new HttpGet(source);
CloseableHttpResponse httpResponse = null;
try
httpResponse = client.execute(httpRequest);
HttpEntity entity = httpResponse.getEntity();
if(httpResponse.getStatusLine() != null && httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
LOGGER.warn(httpResponse.getStatusLine());
else
LOGGER.debug(httpResponse.getStatusLine());
FileUtils.touch(resultingFile);
InputStream is = entity.getContent();
File outFile = new File(resultingFile.getAbsolutePath());
FileOutputStream fos = new FileOutputStream(outFile);
int inByte;
while ((inByte = is.read()) != -1)
fos.write(inByte);
is.close();
fos.close();
client.close();
catch (ClientProtocolException e)
LOGGER.warn(e);
catch (UnsupportedOperationException e)
LOGGER.warn(e);
catch (IOException e)
LOGGER.warn(e);
public static void upload(final File source, final String destination)
CloseableHttpClient httpclient = WinHttpClients.createSystem();
HttpPut httpRequest = new HttpPut(destination);
httpRequest.setEntity(new FileEntity(new File(source.getPath())));
CloseableHttpResponse httpResponse = null;
try
httpResponse = httpclient.execute(httpRequest);
EntityUtils.consume(httpResponse.getEntity());
if (httpResponse.getStatusLine() != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED)
LOGGER.debug(httpResponse.getStatusLine());
LOGGER.info("Upload of " + source.getName() + " via HTTP-Client succeeded.");
else if (httpResponse.getStatusLine() != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
LOGGER.debug(httpResponse.getStatusLine());
else
LOGGER.warn("Uploading " + source.getName() + " failed.");
LOGGER.warn(httpResponse.getStatusLine().getStatusCode() + ": " + httpResponse.getStatusLine().getReasonPhrase());
catch (IOException e)
LOGGER.warn(e);
LOGGER.warn(e.getMessage());
return;
WinHttpClients:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-win</artifactId>
<version>4.4</version>
</dependency>
路径: org.apache.http.impl.client.WinHttpClients
说明: CloseableHttpClient 实例的工厂方法配置为默认使用集成 Windows 身份验证。
【讨论】:
这个签入文件也会上传吗? 这使用像WinHttpClients
这样的非标准类。请编辑您的答案并提及必要的依赖项。
是的,这确实会签入文件
你的代码最近帮了大忙,不管它是否帮助了最初的提问者。我已经更新了依赖项,因为您发布的那个不起作用。
我的工具的最新版本实际上使用了 v4.5.6 的 httpclient 和 httpclient-win以上是关于如何使用 Java 将文档上传到 SharePoint?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jdbc 在 MSSQL 中上传文件(文档)/zip?