Java Webdav File Synchronization

2.3k Views Asked by At

I have a cloud storage at strato namely hidrive. It uses the webdav protocol. Note that it's based on HTTP. The client application they provide is poor and buggy so I tried various other tools for synchronization but none just worked the way I need it.

I'm therefore trying to implement it in Java using the Sardine project. Is there any code for hard-copying a local source folder to an external cloud folder? I haven't found anything in that direction.

The following code is supposed to upload the file...

Sardine sardine = SardineFactory.begin("username", "password");

InputStream fis = new FileInputStream(new File("some/file/test.txt"));
sardine.put("https://webdav.hidrive.strato.com/users/username/Backup", fis);

... but throws an exception instead:

Exception in thread "main" com.github.sardine.impl.SardineException: Unexpected response (301 Moved Permanently)
    at com.github.sardine.impl.handler.ValidatingResponseHandler.validateResponse(ValidatingResponseHandler.java:48)
    at com.github.sardine.impl.handler.VoidResponseHandler.handleResponse(VoidResponseHandler.java:34)
    at com.github.sardine.impl.handler.VoidResponseHandler.handleResponse(VoidResponseHandler.java:1)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:218)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:160)
    at com.github.sardine.impl.SardineImpl.execute(SardineImpl.java:828)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:755)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:738)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:726)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:696)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:689)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:682)
    at com.github.sardine.impl.SardineImpl.put(SardineImpl.java:676)

Printing out the folders in that directory works so the connection/ authentication did succeed:

List<DavResource> resources = sardine.list("https://webdav.hidrive.strato.com/users/username/Backup");

for (DavResource res : resources)
{
    System.out.println(res);
}

Please either help me fix my code or link me to some file synchronization library that works for my purpose.

3

There are 3 best solutions below

2
kulatamicuda On

Sardine uses (internally) HttpClient. There is similar question here where you can find an answer Httpclient 4, error 302. How to redirect?.

1
Augie On

Try converting the InputStream obj into byte array before you call put(). Something like the below,

byte[] fisByte = IOUtils.toByteArray(fis);
sardine.put("https://webdav.hidrive.strato.com/users/username/Backup", fisByte);

It worked for me. Let me know.

0
Jay On

I had to extend the "org.apache.http.impl.client.LaxRedirectStrategy" and also the getRedirect() Method of org.apache.http.impl.client.DefaultRedirectStrategy with a treatment of the needed methods: PUT, MKOL, etc. . By default only GET is redirected.

It looks like this:

private static final String[] REDIRECT_METHODS = new String[] { HttpGet.METHOD_NAME, HttpPost.METHOD_NAME, HttpHead.METHOD_NAME, HttpPut.METHOD_NAME, HttpDelete.METHOD_NAME, HttpMkCol.METHOD_NAME };

isRedirectable-Method

for (final String m : REDIRECT_METHODS) {
  if (m.equalsIgnoreCase(method)) {
    System.out.println("isRedirectable true");
    return true;
  }
}

return method.equalsIgnoreCase(HttpPropFind.METHOD_NAME);

getRedirect-Method:

final URI uri = getLocationURI(request, response, context);
final String method = request.getRequestLine().getMethod();
if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
  return new HttpHead(uri);
} else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
  return new HttpGet(uri);
} else if (method.equalsIgnoreCase(HttpPut.METHOD_NAME)) {

  HttpPut httpPut = new HttpPut(uri);
  httpPut.setEntity(((HttpEntityEnclosingRequest) request).getEntity());
  return httpPut;
} else if (method.equalsIgnoreCase("MKCOL")) {
  return new HttpMkCol(uri);
} else if (method.equalsIgnoreCase("DELETE")) {
  return new HttpDelete(uri);

} else {
  final int status = response.getStatusLine().getStatusCode();

  if (status == HttpStatus.SC_TEMPORARY_REDIRECT) {
    return RequestBuilder.copy(request).setUri(uri).build();
  } else {
    return new HttpGet(uri);
  }
}

That worked for me.