Merge pull request #337 from owncloud/refactor_remote_operation_to_upload_file

Refactor remote operation to upload file
This commit is contained in:
masensio 2013-12-18 00:58:57 -08:00
commit 1638de66f7
12 changed files with 443 additions and 99 deletions

View file

@ -9,7 +9,9 @@
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-sdk
android:minSdkVersion="8"

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -0,0 +1,161 @@
/* ownCloud Android client application
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.oc_framework_test_project.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.res.AssetManager;
import android.os.Environment;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework_test_project.TestActivity;
/**
* Class to test Update File Operation
* @author masensio
*
*/
public class UploadFileTest extends ActivityInstrumentationTestCase2<TestActivity> {
/* Files to upload. These files must exists on the device */
private final String mFileToUpload = "fileToUpload.png";
private final String mMimeType = "image/png";
private final String mFileToUploadWithChunks = "fileToUploadChunks.MP4";
private final String mMimeTypeWithChunks = "video/mp4";
private final String mFileNotFound = "fileNotFound.png";
private final String mStoragePath = "/owncloud/tmp/uploadTest";
private String mPath;
private String mCurrentDate;
private TestActivity mActivity;
public UploadFileTest() {
super(TestActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
mCurrentDate = sdf.format(new Date());
File sdCard = Environment.getExternalStorageDirectory();
mPath = sdCard.getAbsolutePath() + "/" + mStoragePath + mCurrentDate;
//mActivity.createFolder(mPath, true);
copyAssets();
}
/**
* Copy Files to ulpload to SdCard
*/
private void copyAssets() {
AssetManager assetManager = getActivity().getAssets();
String[] files = { mFileToUpload, mFileToUploadWithChunks };
// Folder with contents
File folder = new File(mPath);
folder.mkdirs();
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(folder, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
/**
* Test Upload File without chunks
*/
public void testUploadFile() {
String storagePath = mPath + "/" + mFileToUpload;
//String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload;
String remotePath = "/" + mFileToUpload;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType);
assertTrue(result.isSuccess());
}
/**
* Test Upload File with chunks
*/
public void testUploadFileWithChunks() {
String storagePath = mPath + "/" + mFileToUploadWithChunks;
//String remotePath = "/uploadTest" + mCurrentDate + "/" +mFileToUploadWithChunks;
String remotePath = "/" + mFileToUploadWithChunks;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeTypeWithChunks);
assertTrue(result.isSuccess());
}
/**
* Test Upload Not Found File
*/
public void testUploadFileNotFound() {
String storagePath = mPath + "/" + mFileNotFound;
//String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload;
String remotePath = "/" + mFileNotFound;
RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType);
assertFalse(result.isSuccess());
}
}

View file

@ -3,10 +3,12 @@ package com.owncloud.android.oc_framework_test_project;
import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework.operations.remote.ChunkedUploadRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation;
import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFolderOperation;
import com.owncloud.android.oc_framework.operations.remote.RemoveRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.RenameRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.UploadRemoteFileOperation;
import android.net.Uri;
import android.os.Bundle;
@ -24,6 +26,7 @@ public class TestActivity extends Activity {
private static final String mServerUri = "https://beta.owncloud.com/owncloud/remote.php/webdav";
private static final String mUser = "testandroid";
private static final String mPass = "testandroid";
private static final boolean mChunked = true;
//private Account mAccount = null;
private WebdavClient mClient;
@ -105,4 +108,24 @@ public class TestActivity extends Activity {
return result;
}
/** Access to the library method to Upload a File
* @param storagePath
* @param remotePath
* @param mimeType
*
* @return
*/
public RemoteOperationResult uploadFile(String storagePath, String remotePath, String mimeType) {
UploadRemoteFileOperation uploadOperation;
if (mChunked) {
uploadOperation = new ChunkedUploadRemoteFileOperation(storagePath, remotePath, mimeType);
} else {
uploadOperation = new UploadRemoteFileOperation(storagePath, remotePath, mimeType);
}
RemoteOperationResult result = uploadOperation.execute(mClient);
return result;
}
}

View file

@ -16,7 +16,7 @@
*
*/
package com.owncloud.android.operations;
package com.owncloud.android.oc_framework.operations.remote;
import java.io.File;
import java.io.IOException;
@ -27,32 +27,25 @@ import java.util.Random;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
import com.owncloud.android.utils.Log_OC;
import android.accounts.Account;
import android.util.Log;
public class ChunkedUploadFileOperation extends UploadFileOperation {
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 TAG = ChunkedUploadFileOperation.class.getSimpleName();
public ChunkedUploadFileOperation( Account account,
OCFile file,
boolean isInstant,
boolean forceOverwrite,
int localBehaviour) {
super(account, file, isInstant, forceOverwrite, localBehaviour);
}
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) {
super(storagePath, remotePath, mimeType);
}
@Override
protected int uploadFile(WebdavClient client) throws HttpException, IOException {
int status = -1;
@ -60,13 +53,17 @@ public class ChunkedUploadFileOperation extends UploadFileOperation {
FileChannel channel = null;
RandomAccessFile raf = null;
try {
File file = new File(getStoragePath());
File file = new File(mStoragePath);
raf = new RandomAccessFile(file, "r");
channel = raf.getChannel();
mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
//((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
synchronized (mDataTransferListeners) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
}
long offset = 0;
String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(mRemotePath) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
if (mPutMethod != null) {
@ -78,7 +75,7 @@ public class ChunkedUploadFileOperation extends UploadFileOperation {
mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
Log_OC.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
Log.d(TAG, "Upload of " + mStoragePath + " to " + mRemotePath + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
if (!isSuccess(status))
break;
}

View file

@ -15,7 +15,7 @@
*
*/
package com.owncloud.android.operations;
package com.owncloud.android.oc_framework.operations.remote;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.HeadMethod;
@ -24,22 +24,22 @@ import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
import com.owncloud.android.utils.Log_OC;
import android.content.Context;
import android.net.ConnectivityManager;
import android.util.Log;
/**
* Operation to check the existence or absence of a path in a remote server.
*
* @author David A. Velasco
*/
public class ExistenceCheckOperation extends RemoteOperation {
public class ExistenceCheckRemoteOperation extends RemoteOperation {
/** Maximum time to wait for a response from the server in MILLISECONDs. */
public static final int TIMEOUT = 10000;
private static final String TAG = ExistenceCheckOperation.class.getSimpleName();
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
private String mPath;
private Context mContext;
@ -53,7 +53,7 @@ public class ExistenceCheckOperation extends RemoteOperation {
* @param context Android application context.
* @param successIfAbsent When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404).
*/
public ExistenceCheckOperation(String path, Context context, boolean successIfAbsent) {
public ExistenceCheckRemoteOperation(String path, Context context, boolean successIfAbsent) {
mPath = (path != null) ? path : "";
mContext = context;
mSuccessIfAbsent = successIfAbsent;
@ -73,11 +73,11 @@ public class ExistenceCheckOperation extends RemoteOperation {
client.exhaustResponse(head.getResponseBodyAsStream());
boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
result = new RemoteOperationResult(success, status, head.getResponseHeaders());
Log_OC.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":""));
Log.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":""));
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log_OC.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException());
Log.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException());
} finally {
if (head != null)

View file

@ -0,0 +1,147 @@
/* ownCloud Android client application
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.oc_framework.operations.remote;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.http.HttpStatus;
import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity;
import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
import com.owncloud.android.oc_framework.operations.OperationCancelledException;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
/**
* Remote operation performing the upload of a remote file to the ownCloud server.
*
* @author David A. Velasco
* @author masensio
*/
public class UploadRemoteFileOperation extends RemoteOperation {
protected String mStoragePath;
protected String mRemotePath;
protected String mMimeType;
protected PutMethod mPutMethod = null;
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
protected RequestEntity mEntity = null;
public UploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) {
mStoragePath = storagePath;
mRemotePath = remotePath;
mMimeType = mimeType;
}
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
try {
// / perform the upload
synchronized (mCancellationRequested) {
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
} else {
mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
}
}
int status = uploadFile(client);
result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
} catch (Exception e) {
// TODO something cleaner with cancellations
if (mCancellationRequested.get()) {
result = new RemoteOperationResult(new OperationCancelledException());
} else {
result = new RemoteOperationResult(e);
}
}
return result;
}
public boolean isSuccess(int status) {
return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
}
protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
int status = -1;
try {
File f = new File(mStoragePath);
mEntity = new FileRequestEntity(f, mMimeType);
synchronized (mDataTransferListeners) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
}
mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
} finally {
mPutMethod.releaseConnection(); // let the connection available for other methods
}
return status;
}
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
return mDataTransferListeners;
}
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.add(listener);
}
if (mEntity != null) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
}
}
public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
synchronized (mDataTransferListeners) {
mDataTransferListeners.remove(listener);
}
if (mEntity != null) {
((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
}
}
public void cancel() {
synchronized (mCancellationRequested) {
mCancellationRequested.set(true);
if (mPutMethod != null)
mPutMethod.abort();
}
}
}

View file

@ -57,13 +57,13 @@ import com.owncloud.android.oc_framework.accounts.AccountTypeUtils;
import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.operations.ExistenceCheckOperation;
import com.owncloud.android.operations.OAuth2GetAccessToken;
import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.OwnCloudServerCheckOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation;
import com.owncloud.android.ui.dialog.SamlWebViewDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
@ -131,7 +131,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
private final Handler mHandler = new Handler();
private Thread mOperationThread;
private OwnCloudServerCheckOperation mOcServerChkOperation;
private ExistenceCheckOperation mAuthCheckOperation;
private ExistenceCheckRemoteOperation mAuthCheckOperation;
private RemoteOperationResult mLastSslUntrustedServerResult;
private Uri mNewCapturedUriFromOAuth2Redirection;
@ -716,7 +716,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
showDialog(DIALOG_LOGIN_PROGRESS);
/// test credentials accessing the root folder
mAuthCheckOperation = new ExistenceCheckOperation("", this, false);
mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false);
WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);
client.setBasicCredentials(username, password);
mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);
@ -765,7 +765,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, mAuthTokenType);
/// test credentials accessing the root folder
mAuthCheckOperation = new ExistenceCheckOperation("", this, false);
mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false);
WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false);
mOperationThread = mAuthCheckOperation.execute(client, this, mHandler);
@ -785,12 +785,12 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
} else if (operation instanceof OAuth2GetAccessToken) {
onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);
} else if (operation instanceof ExistenceCheckOperation) {
} else if (operation instanceof ExistenceCheckRemoteOperation) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
onSamlBasedFederatedSingleSignOnAuthorizationStart(operation, result);
} else {
onAuthorizationCheckFinish((ExistenceCheckOperation)operation, result);
onAuthorizationCheckFinish((ExistenceCheckRemoteOperation)operation, result);
}
}
}
@ -1084,7 +1084,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
/// time to test the retrieved access token on the ownCloud server
mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);
Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);
mAuthCheckOperation = new ExistenceCheckOperation("", this, false);
mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false);
WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true);
client.setBearerCredentials(mAuthToken);
mAuthCheckOperation.execute(client, this, mHandler);
@ -1105,7 +1105,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList
* @param operation Access check performed.
* @param result Result of the operation.
*/
private void onAuthorizationCheckFinish(ExistenceCheckOperation operation, RemoteOperationResult result) {
private void onAuthorizationCheckFinish(ExistenceCheckRemoteOperation operation, RemoteOperationResult result) {
try {
dismissDialog(DIALOG_LOGIN_PROGRESS);
} catch (IllegalArgumentException e) {

View file

@ -38,17 +38,15 @@ import com.owncloud.android.authentication.AuthenticatorActivity;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.operations.ChunkedUploadFileOperation;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.ExistenceCheckOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation;
import com.owncloud.android.oc_framework.utils.OwnCloudVersion;
import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
import com.owncloud.android.oc_framework.accounts.OwnCloudAccount;
import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity;
import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.network.webdav.WebdavEntry;
@ -253,7 +251,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes != null) ? mimeTypes[i]
: (String) null), storageManager);
if (files[i] == null) {
// TODO @andomaex add failure Notiification
// TODO @andomaex add failure Notification
return Service.START_NOT_STICKY;
}
}
@ -267,14 +265,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
try {
for (int i = 0; i < files.length; i++) {
uploadKey = buildRemoteName(account, files[i].getRemotePath());
if (chunked
&& (new File(files[i].getStoragePath())).length() > ChunkedUploadFileOperation.CHUNK_SIZE) // added to work around bug in servers 5.x
{
newUpload = new ChunkedUploadFileOperation(account, files[i], isInstant, forceOverwrite,
localAction);
} else {
newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction);
}
newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction,
getApplicationContext());
// if (chunked) {
// newUpload = new ChunkedUploadFileOperation(account, files[i], isInstant, forceOverwrite,
// localAction, getApplicationContext());
// } else {
// newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction,
// getApplicationContext());
// }
if (isInstant) {
newUpload.setRemoteFolderToBeCreated();
}
@ -563,7 +562,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
* @return An {@link OCFile} instance corresponding to the folder where the file will be uploaded.
*/
private RemoteOperationResult grantFolderExistence(String pathToGrant) {
RemoteOperation operation = new ExistenceCheckOperation(pathToGrant, this, false);
RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false);
RemoteOperationResult result = operation.execute(mUploadClient);
if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) {
operation = new CreateFolderOperation( pathToGrant,

View file

@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@ -38,15 +39,18 @@ import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity;
import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener;
import com.owncloud.android.oc_framework.network.webdav.WebdavClient;
import com.owncloud.android.oc_framework.network.webdav.WebdavUtils;
import com.owncloud.android.oc_framework.operations.OperationCancelledException;
import com.owncloud.android.oc_framework.operations.RemoteOperation;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult;
import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.oc_framework.operations.remote.ChunkedUploadRemoteFileOperation;
import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation;
import com.owncloud.android.oc_framework.operations.remote.UploadRemoteFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.Log_OC;
import android.accounts.Account;
import android.content.Context;
/**
@ -62,6 +66,7 @@ public class UploadFileOperation extends RemoteOperation {
private OCFile mFile;
private OCFile mOldFile;
private String mRemotePath = null;
private boolean mChunked = false;
private boolean mIsInstant = false;
private boolean mRemoteFolderToBeCreated = false;
private boolean mForceOverwrite = false;
@ -72,15 +77,20 @@ public class UploadFileOperation extends RemoteOperation {
PutMethod mPutMethod = null;
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
private Context mContext;
private UploadRemoteFileOperation mUploadOperation;
protected RequestEntity mEntity = null;
public UploadFileOperation( Account account,
OCFile file,
boolean chunked,
boolean isInstant,
boolean forceOverwrite,
int localBehaviour) {
int localBehaviour,
Context context) {
if (account == null)
throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation");
if (file == null)
@ -95,11 +105,13 @@ public class UploadFileOperation extends RemoteOperation {
mAccount = account;
mFile = file;
mRemotePath = file.getRemotePath();
mChunked = chunked;
mIsInstant = isInstant;
mForceOverwrite = forceOverwrite;
mLocalBehaviour = localBehaviour;
mOriginalStoragePath = mFile.getStoragePath();
mOriginalFileName = mFile.getFileName();
mContext = context;
}
public Account getAccount() {
@ -199,7 +211,7 @@ public class UploadFileOperation extends RemoteOperation {
// !!!
expectedFile = new File(expectedPath);
// / check location of local file; if not the expected, copy to a
// check location of local file; if not the expected, copy to a
// temporal file before upload (if COPY is the expected behaviour)
if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) {
@ -260,19 +272,23 @@ public class UploadFileOperation extends RemoteOperation {
}
localCopyPassed = true;
// / perform the upload
synchronized (mCancellationRequested) {
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
} else {
mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath()));
}
/// perform the upload
if (mChunked) {
mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(),
mFile.getMimetype());
} else {
mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(),
mFile.getMimetype());
}
int status = uploadFile(client);
Iterator <OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
while (listener.hasNext()) {
mUploadOperation.addDatatransferProgressListener(listener.next());
}
result = mUploadOperation.execute(client);
// / move local temporal file or original file to its corresponding
/// move local temporal file or original file to its corresponding
// location in the ownCloud local folder
if (isSuccess(status)) {
if (result.isSuccess()) {
if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
mFile.setStoragePath(null);
@ -305,8 +321,6 @@ public class UploadFileOperation extends RemoteOperation {
}
}
result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
} catch (Exception e) {
// TODO something cleaner with cancellations
if (mCancellationRequested.get()) {
@ -358,28 +372,28 @@ public class UploadFileOperation extends RemoteOperation {
mFile = newFile;
}
public boolean isSuccess(int status) {
return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
}
protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
int status = -1;
try {
File f = new File(mFile.getStoragePath());
mEntity = new FileRequestEntity(f, getMimeType());
synchronized (mDataTransferListeners) {
((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
}
mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
} finally {
mPutMethod.releaseConnection(); // let the connection available for
// other methods
}
return status;
}
// public boolean isSuccess(int status) {
// return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
// }
//
// protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
// int status = -1;
// try {
// File f = new File(mFile.getStoragePath());
// mEntity = new FileRequestEntity(f, getMimeType());
// synchronized (mDataTransferListeners) {
// ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
// }
// mPutMethod.setRequestEntity(mEntity);
// status = client.executeMethod(mPutMethod);
// client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
//
// } finally {
// mPutMethod.releaseConnection(); // let the connection available for
// // other methods
// }
// return status;
// }
/**
* Checks if remotePath does not exist in the server and returns it, or adds
@ -389,7 +403,7 @@ public class UploadFileOperation extends RemoteOperation {
* @return
*/
private String getAvailableRemotePath(WebdavClient wc, String remotePath) throws Exception {
boolean check = wc.existsFile(remotePath);
boolean check = existsFile(wc, remotePath);
if (!check) {
return remotePath;
}
@ -404,10 +418,12 @@ public class UploadFileOperation extends RemoteOperation {
int count = 2;
do {
suffix = " (" + count + ")";
if (pos >= 0)
check = wc.existsFile(remotePath + suffix + "." + extension);
else
check = wc.existsFile(remotePath + suffix);
if (pos >= 0) {
check = existsFile(wc, remotePath + suffix + "." + extension);
}
else {
check = existsFile(wc, remotePath + suffix);
}
count++;
} while (check);
@ -418,12 +434,14 @@ public class UploadFileOperation extends RemoteOperation {
}
}
private boolean existsFile(WebdavClient client, String remotePath){
ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false);
RemoteOperationResult result = existsOperation.execute(client);
return result.isSuccess();
}
public void cancel() {
synchronized (mCancellationRequested) {
mCancellationRequested.set(true);
if (mPutMethod != null)
mPutMethod.abort();
}
mUploadOperation.cancel();
}
}

View file

@ -28,9 +28,6 @@ import java.util.Vector;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.R.id;
import com.owncloud.android.R.layout;
import com.owncloud.android.R.string;
import com.owncloud.android.authentication.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;