RE: "PUT" to a Microsoft Sharepoint working with Slide
"Miguel Figueiredo" <[email protected]>
| Newsgroups | gmane.comp.jakarta.slide.user |
|---|---|
| Message-ID | <[email protected]> |
Hey Chandler, Many thanks for this important piece of the information! I'm sure it can be used in many other situations related with NTLM authentication. Best regards, Miguel Figueiredo -----Original Message----- From: Andy Chandler [mailto:[email protected]] Sent: quarta-feira, 13 de Dezembro de 2006 17:53 To: [email protected] Subject: "PUT" to a Microsoft Sharepoint working with Slide Well since I've seen others with similar issues I thought I'd share how I managed to get it working - it does take a modification to both the slide and the httpclient libraries. Please Note I've done my work with HTTPClient 3.01 and Slide 2.1 (I've also done the same work with the trunks of both projects and the result is the same) Problem: Need to upload files to Microsoft Sharepoint with NTLM authentication. NTLM authentication will cause an exception about unbuffered enclosing entity can't be resent or retried (I'm sorry I no longer get the message so I can't paste it in). Contrary to other messages if the server is Microsoft and the client is java turning off expect-continue does not fix the problem. The problem stems from the fact that the Put Method on http client is setting the size of the content when it creates an InputStreamRequestEntity. This causes the entity to not buffer itself (Why you would want this I don't know since it only buffers 4k at a time). I haven't tried large files yet so there may still be additional work that has to be done to get this to work out correctly if the file is large. Anyhow the buffering is important simply because when you try to put a file to an NTLM authenticated resource the first attempt will fail with a not authorized. This will cause a challenge response handshake and then a retry happens. The problem is with an unbuffered input stream the retry does not occur because the enclosing entity claims its not repeatable. Failure every time. My solution which is not necessarily elegant but may help some desperate developer out there consists of the following changes: 1: In the jakarta.commons.httpclient project modify: org.apache.commons.httpclient.methods.InputStreamRequestEntity When contentlength is declared set it equal to CONTENT_LENGTH_AUTO // This change is probably not absolutely required but its what I did. org.apache.commons.httpclient.methods.EntityEnclosingMethod Modify method generateRequestEntity -> change the new for new InputStreamRequestEntity to use the single arge constructor as in " new InputStreamRequestEntity(is)" // By not passing the size it stays in CONTENT_LENGTH_AUTO mode which permits buffering. 2: In the Slide webdavclient project modify org.apache.webdav.lib.WebdavResource In the put(String,InputStream) method remove the content length "chunked" set command. Sample code that now works: public static void main(String[] args){ try { File file = new File(src); if (file.exists()) { System.out.println("Uploading '" + file.getCanonicalPath() + "' to '" + dest + "' "); uploadWebDav(file); } catch (Exception e) { System.out.println(e.getMessage()); } private static void uploadWebDav(File file) { WebdavResource webdavResource = null; try { NTCredentials creds2 = new NTCredentials("myusername", "mypassword", "myclientpc", "NTDOMAIN"); webdavResource = new WebdavResource( "http://SHAREPOINTSERVER/Shared Documents", creds2); String[] list = webdavResource.list(); for (String s :list){ System.out.println(s); } System.out.println("Uploading"); // Note - use the putmethod where specify a destination path and that you include the desired filename!!!! if (webdavResource.putMethod("http://SHAREPOINTSERVER/Shared Documents/cofs9.zip" , new FileInputStream(file))) { System.out.println("succeeded."); } } catch (Exception e1) { System.out.println(e1.getMessage()); } }