如何使用 Java 将文档上传到 SharePoint?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/314258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:02:24  来源:igfitidea点击:

How do I upload a document to SharePoint with Java?

javasharepointsoapupload

提问by Aaron Digulla

I'm creating some big files (DB exports) with Java and I need to put them somewhere on our SharePoint server. Right now, I'm doing this with IE but I'd like to automate this step, too.

我正在使用 Java 创建一些大文件(DB 导出),我需要将它们放在我们的 SharePoint 服务器上的某个位置。现在,我正在使用 IE 执行此操作,但我也想自动执行此步骤。

I searched the web and I found some hints to use SOAP but I don't really see to the ground of all this, yet. Can someone provide me with some sample code or a recipe what I need to do?

我搜索了网络,发现了一些使用 SOAP 的提示,但我还没有真正了解这一切。有人可以为我提供一些示例代码或我需要做什么的食谱吗?

Please note: the SharePoint server asks for NT domain authentication. I can't even login with Firefox :(

请注意:SharePoint 服务器要求进行 NT 域身份验证。我什至无法使用 Firefox 登录 :(

EDIT

编辑

  • How do I convert the scary URL in IE into a WebDAV path?
  • Is there a WebDAV "explorer" which I can use before I ruin the production system with my code? I tried "DAV Explorer 0.91" from http://www.davexplorer.org/but that can't connect (probably because of NT domain auth).
  • 如何将 IE 中可怕的 URL 转换为 WebDAV 路径?
  • 在我用我的代码破坏生产系统之前,是否有我可以使用的 WebDAV“资源管理器”?我从http://www.davexplorer.org/尝试了“DAV Explorer 0.91”,但无法连接(可能是因为 NT 域身份验证)。

采纳答案by Aaron Digulla

Okay ... after several hours of work and biting myself through the "documentation" MicroSoft provides and all the hints randomly spread over the 'net, I've managed to write some sample code to browse the content of a SharePoint server: Navigating SharePoint Folders With Axis2.

好的...经过几个小时的工作并仔细阅读了 MicroSoft 提供的“文档”以及随机散布在网络上的所有提示,我设法编写了一些示例代码来浏览 SharePoint 服务器的内容:导航 SharePoint Axis2 文件夹

Next stop: Uploading something.

下一站:上传东西。

回答by sachaa

I can think of different options:

我可以想到不同的选择:

  • Mapping the Document library to a file drive and just save the file like any other file in the file system.
  • Using HTTP WebDAV protocol.
  • 将文档库映射到文件驱动器,然后像保存文件系统中的任何其他文件一样保存该文件。
  • 使用 HTTP WebDAV 协议。

...and for the NTLM authentication part:

...对于 NTLM 身份验证部分:

http://www.luigidragone.com/networking/ntlm.html

http://www.luigidragone.com/networking/ntlm.html

回答by dariom

In addition to Sacha's suggestions, you can use the SharePoint SOAP web services. Each SharePoint site exposes a bunch of web services via the path http://<Site>/_vti_bin/.

除了Sacha 的建议,您还可以使用 SharePoint SOAP Web 服务。每个 SharePoint 站点都通过路径公开一组 Web 服务http://<Site>/_vti_bin/

In your case, you probably want the Lists web service(http://<Site>/_vti_bin/Lists.asmx). You can grab the WSDL from http://<Site>/_vti_bin/Lists.asmx?WSDL. The WSS 3.0 SDK has details on how to use the web service (you'll probably want to use the UpdateListItemsand AddAttachmentmethods).

在您的情况下,您可能需要Lists Web 服务( http://<Site>/_vti_bin/Lists.asmx)。您可以从http://<Site>/_vti_bin/Lists.asmx?WSDL. WSS 3.0 SDK 提供了有关如何使用 Web 服务的详细信息(您可能希望使用UpdateListItemsAddAttachment方法)。

All that said, Sacha's first option (mapping a document library to a drive) is probably the easiest way assuming you can get around the NTLM issues.

尽管如此,假设您可以解决 NTLM 问题,Sacha 的第一个选项(将文档库映射到驱动器)可能是最简单的方法。

If you're using Windows you can simply navigate to a UNC path for a document library. For example, if the browser URL for your document library is:

如果您使用的是 Windows,则只需导航到文档库的 UNC 路径即可。例如,如果您的文档库的浏览器 URL 是:

http://<Site>/Foo/BarDocs/Forms/AllItems.aspx

http://<Site>/Foo/BarDocs/Forms/AllItems.aspx

you can simply type the corresponding UNC path in the Windows Explorer address bar:

您可以简单地在 Windows 资源管理器地址栏中键入相应的 UNC 路径:

\\<Site>\Foo\BarDocs

\\<Site>\Foo\BarDocs

and then drag and drop files to this location. If you'd like you can map this location to a drive letter using Windows Explorer or the SUBST.EXE command-line utility.

然后将文件拖放到该位置。如果您愿意,可以使用 Windows 资源管理器或 SUBST.EXE 命令行实用程序将此位置映射到驱动器号。

回答by DMEx38

An other solution is to use HTTP PUT methodto send a file directly to the Sharepoint.

另一种解决方案是使用HTTP PUT 方法将文件直接发送到 Sharepoint。

For that you can use Apache HTTP Client:

为此,您可以使用Apache HTTP 客户端

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.3</version>
</dependency>

And to permit NTLMv2 authentication you need JCIFlibrary.

要允许 NTLMv2 身份验证,您需要JCIF库。

<dependency>
   <groupId>jcifs</groupId>
   <artifactId>jcifs</artifactId>
   <version>1.3.17</version>
</dependency>

First we need to write a wrapper to permit Apache HTTP Client to use JCIF for NTLMv2 support :

首先,我们需要编写一个包装器来允许 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

参考

The main code to execute HTTP PUT with authentication:

使用身份验证执行 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) {
      //...
    }

回答by Monkey D. Luffy

I think my approach might help you.

我想我的方法可能对你有帮助。

Initially i have created sharepoint account and followed the procedure in this link (http://www.ktskumar.com/2017/01/access-sharepoint-online-using-postman/) to get needed credentials for REST API's. once i got the credentials all i needed was the following dependency and code:

最初,我创建了 sharepoint 帐户并按照此链接 ( 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>

Since i used OAUTH2 authentication, the code to get access token helps for other CRUD operations.

由于我使用了 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;
}

Once we get access token we can upload using following method:

获得访问令牌后,我们可以使用以下方法上传:

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;
}

回答by go4X

I managed to up and download files to sharepoint with this code, using the integrated Windows identification, maybe it helps.

我设法使用集成的 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:

WinHttp客户端:

 <dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpclient-win</artifactId>
     <version>4.4</version>
 </dependency> 

Path:
org.apache.http.impl.client.WinHttpClients

路径:
org.apache.http.impl.client.WinHttpClients

Description:
Factory methods for CloseableHttpClient instances configured to use integrated Windows authentication by default.

说明:
默认情况下配置为使用集成 Windows 身份验证的 CloseableHttpClient 实例的工厂方法。