diff --git a/sample_client/src/com/owncloud/android/lib/sampleclient/MainActivity.java b/sample_client/src/com/owncloud/android/lib/sampleclient/MainActivity.java index 09db872f..31cf1c79 100644 --- a/sample_client/src/com/owncloud/android/lib/sampleclient/MainActivity.java +++ b/sample_client/src/com/owncloud/android/lib/sampleclient/MainActivity.java @@ -154,10 +154,15 @@ public class MainActivity extends Activity implements OnRemoteOperationListener, private void startUpload() { File upFolder = new File(getCacheDir(), getString(R.string.upload_folder_path)); - File fileToUpload = upFolder.listFiles()[0]; + File fileToUpload = upFolder.listFiles()[0]; String remotePath = FileUtils.PATH_SEPARATOR + fileToUpload.getName(); String mimeType = getString(R.string.sample_file_mimetype); - UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType); + + // Get the last modification date of the file from the file system + Long timeStampLong = fileToUpload.lastModified()/1000; + String timeStamp = timeStampLong.toString(); + + UploadRemoteFileOperation uploadOperation = new UploadRemoteFileOperation(fileToUpload.getAbsolutePath(), remotePath, mimeType, timeStamp); uploadOperation.addDatatransferProgressListener(this); uploadOperation.execute(mClient, this, mHandler); } diff --git a/src/com/owncloud/android/lib/resources/files/ChunkedUploadRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/ChunkedUploadRemoteFileOperation.java index d5dd096f..3135a788 100644 --- a/src/com/owncloud/android/lib/resources/files/ChunkedUploadRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/ChunkedUploadRemoteFileOperation.java @@ -49,16 +49,19 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation public static final long CHUNK_SIZE = 1024000; private static final String OC_CHUNKED_HEADER = "OC-Chunked"; private static final String OC_CHUNK_SIZE_HEADER = "OC-Chunk-Size"; + private static final String OC_CHUNK_X_OC_MTIME_HEADER = "X-OC-Mtime"; private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName(); - public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType){ - super(storagePath, remotePath, mimeType); + public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType, + String fileLastModifTimestamp){ + super(storagePath, remotePath, mimeType, fileLastModifTimestamp); } public ChunkedUploadRemoteFileOperation( - String storagePath, String remotePath, String mimeType, String requiredEtag + String storagePath, String remotePath, String mimeType, String requiredEtag, + String fileLastModifTimestamp ){ - super(storagePath, remotePath, mimeType, requiredEtag); + super(storagePath, remotePath, mimeType, requiredEtag, fileLastModifTimestamp); } @Override @@ -99,6 +102,9 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); mPutMethod.addRequestHeader(OC_CHUNK_SIZE_HEADER, chunkSizeStr); mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, totalLengthStr); + + mPutMethod.addRequestHeader(OC_CHUNK_X_OC_MTIME_HEADER, mFileLastModifTimestamp); + ((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset); mPutMethod.setRequestEntity(mEntity); if (mCancellationRequested.get()) { diff --git a/src/com/owncloud/android/lib/resources/files/UploadRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/UploadRemoteFileOperation.java index 0f1b7cf7..1f5ecb19 100644 --- a/src/com/owncloud/android/lib/resources/files/UploadRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/UploadRemoteFileOperation.java @@ -58,124 +58,132 @@ import com.owncloud.android.lib.common.utils.Log_OC; public class UploadRemoteFileOperation extends RemoteOperation { - private static final String TAG = UploadRemoteFileOperation.class.getSimpleName(); + private static final String TAG = UploadRemoteFileOperation.class.getSimpleName(); - protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length"; - protected static final String IF_MATCH_HEADER = "If-Match"; + protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length"; + protected static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime"; + protected static final String IF_MATCH_HEADER = "If-Match"; - protected String mLocalPath; - protected String mRemotePath; - protected String mMimeType; - protected PutMethod mPutMethod = null; - protected boolean mForbiddenCharsInServer = false; - protected String mRequiredEtag = null; - - protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); - protected Set mDataTransferListeners = new HashSet(); + protected String mLocalPath; + protected String mRemotePath; + protected String mMimeType; + protected String mFileLastModifTimestamp; + protected PutMethod mPutMethod = null; + protected boolean mForbiddenCharsInServer = false; + protected String mRequiredEtag = null; - protected RequestEntity mEntity = null; + protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + protected Set mDataTransferListeners = new HashSet(); - public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType) { - mLocalPath = localPath; - mRemotePath = remotePath; - mMimeType = mimeType; - } + protected RequestEntity mEntity = null; - public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, String requiredEtag) { - this(localPath, remotePath, mimeType); - mRequiredEtag = requiredEtag; - } + public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, + String fileLastModifTimestamp) { + mLocalPath = localPath; + mRemotePath = remotePath; + mMimeType = mimeType; + mFileLastModifTimestamp = fileLastModifTimestamp; + } - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = null; - DefaultHttpMethodRetryHandler oldRetryHandler = - (DefaultHttpMethodRetryHandler) client.getParams().getParameter(HttpMethodParams.RETRY_HANDLER); + public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, + String requiredEtag, String fileLastModifTimestamp) { + this(localPath, remotePath, mimeType, fileLastModifTimestamp); + mRequiredEtag = requiredEtag; + } - try { - // prevent that uploads are retried automatically by network library - client.getParams().setParameter( - HttpMethodParams.RETRY_HANDLER, - new DefaultHttpMethodRetryHandler(0, false) - ); + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + DefaultHttpMethodRetryHandler oldRetryHandler = + (DefaultHttpMethodRetryHandler) client.getParams().getParameter(HttpMethodParams.RETRY_HANDLER); - mPutMethod = new PutMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath)); + try { + // prevent that uploads are retried automatically by network library + client.getParams().setParameter( + HttpMethodParams.RETRY_HANDLER, + new DefaultHttpMethodRetryHandler(0, false) + ); - if (mCancellationRequested.get()) { - // the operation was cancelled before getting it's turn to be executed in the queue of uploads - result = new RemoteOperationResult(new OperationCancelledException()); + mPutMethod = new PutMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath)); - } else { - // perform the upload - int status = uploadFile(client); - if (mForbiddenCharsInServer){ - result = new RemoteOperationResult( - RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER); - } else { - result = new RemoteOperationResult(isSuccess(status), status, - (mPutMethod != null ? mPutMethod.getResponseHeaders() : null)); - } - } + if (mCancellationRequested.get()) { + // the operation was cancelled before getting it's turn to be executed in the queue of uploads + result = new RemoteOperationResult(new OperationCancelledException()); - } catch (Exception e) { - if (mPutMethod != null && mPutMethod.isAborted()) { - result = new RemoteOperationResult(new OperationCancelledException()); + } else { + // perform the upload + int status = uploadFile(client); + if (mForbiddenCharsInServer){ + result = new RemoteOperationResult( + RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER); + } else { + result = new RemoteOperationResult(isSuccess(status), status, + (mPutMethod != null ? mPutMethod.getResponseHeaders() : null)); + } + } - } else { - result = new RemoteOperationResult(e); - } - } finally { - // reset previous retry handler - client.getParams().setParameter( - HttpMethodParams.RETRY_HANDLER, - oldRetryHandler - ); - } - return result; - } + } catch (Exception e) { + if (mPutMethod != null && mPutMethod.isAborted()) { + result = new RemoteOperationResult(new OperationCancelledException()); - public boolean isSuccess(int status) { - return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || + } else { + result = new RemoteOperationResult(e); + } + } finally { + // reset previous retry handler + client.getParams().setParameter( + HttpMethodParams.RETRY_HANDLER, + oldRetryHandler + ); + } + return result; + } + + public boolean isSuccess(int status) { + return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT)); - } + } - protected int uploadFile(OwnCloudClient client) throws IOException { - int status = -1; - try { - File f = new File(mLocalPath); - mEntity = new FileRequestEntity(f, mMimeType); - synchronized (mDataTransferListeners) { - ((ProgressiveDataTransferer)mEntity) + protected int uploadFile(OwnCloudClient client) throws IOException { + int status = -1; + try { + File f = new File(mLocalPath); + mEntity = new FileRequestEntity(f, mMimeType); + synchronized (mDataTransferListeners) { + ((ProgressiveDataTransferer)mEntity) .addDatatransferProgressListeners(mDataTransferListeners); - } - if (mRequiredEtag != null && mRequiredEtag.length() > 0) { - mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\""); - } - mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length())); - mPutMethod.setRequestEntity(mEntity); - status = client.executeMethod(mPutMethod); + } + if (mRequiredEtag != null && mRequiredEtag.length() > 0) { + mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\""); + } + mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length())); - if (status == 400) { - InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser(); - InputStream is = new ByteArrayInputStream( - mPutMethod.getResponseBodyAsString().getBytes()); - try { - mForbiddenCharsInServer = xmlParser.parseXMLResponse(is); + mPutMethod.addRequestHeader(OC_X_OC_MTIME_HEADER, mFileLastModifTimestamp); - } catch (Exception e) { - mForbiddenCharsInServer = false; - Log_OC.e(TAG, "Exception reading exception from server", e); - } - } + mPutMethod.setRequestEntity(mEntity); + status = client.executeMethod(mPutMethod); - client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); + if (status == 400) { + InvalidCharacterExceptionParser xmlParser = new InvalidCharacterExceptionParser(); + InputStream is = new ByteArrayInputStream( + mPutMethod.getResponseBodyAsString().getBytes()); + try { + mForbiddenCharsInServer = xmlParser.parseXMLResponse(is); + + } catch (Exception e) { + mForbiddenCharsInServer = false; + Log_OC.e(TAG, "Exception reading exception from server", e); + } + } + + client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); + + } finally { + mPutMethod.releaseConnection(); // let the connection available for other methods + } + return status; + } - } finally { - mPutMethod.releaseConnection(); // let the connection available for other methods - } - return status; - } - public Set getDataTransferListeners() { return mDataTransferListeners; } diff --git a/test_client/src/com/owncloud/android/lib/test_project/TestActivity.java b/test_client/src/com/owncloud/android/lib/test_project/TestActivity.java index ec4314f7..4bc107fe 100644 --- a/test_client/src/com/owncloud/android/lib/test_project/TestActivity.java +++ b/test_client/src/com/owncloud/android/lib/test_project/TestActivity.java @@ -249,10 +249,10 @@ public class TestActivity extends Activity { public RemoteOperationResult uploadFile( String storagePath, String remotePath, String mimeType ) { + return TestActivity.uploadFile(storagePath, remotePath, mimeType, mClient); } - /** Access to the library method to Upload a File * @param storagePath * @param remotePath @@ -264,14 +264,18 @@ public class TestActivity extends Activity { public static RemoteOperationResult uploadFile( String storagePath, String remotePath, String mimeType, OwnCloudClient client ) { - UploadRemoteFileOperation uploadOperation; + + String fileLastModifTimestamp = getFileLastModifTimeStamp(storagePath); + + UploadRemoteFileOperation uploadOperation; + if ((new File(storagePath)).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) { uploadOperation = new ChunkedUploadRemoteFileOperation( - storagePath, remotePath, mimeType + storagePath, remotePath, mimeType, fileLastModifTimestamp ); } else { uploadOperation = new UploadRemoteFileOperation( - storagePath, remotePath, mimeType + storagePath, remotePath, mimeType, fileLastModifTimestamp ); } @@ -381,5 +385,9 @@ public class TestActivity extends Activity { return extractedFile; } - + private static String getFileLastModifTimeStamp (String storagePath) { + File file = new File(storagePath); + Long timeStampLong = file.lastModified()/1000; + return timeStampLong.toString(); + } } diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/UploadFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/UploadFileTest.java index 07854575..eeb6a24c 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/UploadFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/UploadFileTest.java @@ -69,7 +69,7 @@ public class UploadFileTest extends RemoteTest { * Test Upload File without chunks */ public void testUploadFile() { - + String fullPath2Upload = mBaseFolderPath + UPLOAD_PATH; RemoteOperationResult result = mActivity.uploadFile( mFileToUpload.getAbsolutePath(), @@ -121,5 +121,4 @@ public class UploadFileTest extends RemoteTest { } super.tearDown(); } - }