1 /* ownCloud Android client application 
   2  *   Copyright (C) 2012 Bartek Przybylski 
   3  *   Copyright (C) 2012-2013 ownCloud Inc. 
   5  *   This program is free software: you can redistribute it and/or modify 
   6  *   it under the terms of the GNU General Public License version 2, 
   7  *   as published by the Free Software Foundation. 
   9  *   This program is distributed in the hope that it will be useful, 
  10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  12  *   GNU General Public License for more details. 
  14  *   You should have received a copy of the GNU General Public License 
  15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  19 package com
.owncloud
.android
.operations
; 
  22 import java
.io
.IOException
; 
  23 import java
.io
.RandomAccessFile
; 
  24 import java
.nio
.channels
.FileChannel
; 
  25 import java
.util
.Random
; 
  27 import org
.apache
.commons
.httpclient
.HttpException
; 
  28 import org
.apache
.commons
.httpclient
.methods
.PutMethod
; 
  30 import com
.owncloud
.android
.Log_OC
; 
  31 import com
.owncloud
.android
.datamodel
.OCFile
; 
  32 import com
.owncloud
.android
.network
.ProgressiveDataTransferer
; 
  35 import android
.accounts
.Account
; 
  37 import eu
.alefzero
.webdav
.ChunkFromFileChannelRequestEntity
; 
  38 import eu
.alefzero
.webdav
.WebdavClient
; 
  39 import eu
.alefzero
.webdav
.WebdavUtils
; 
  41 public class ChunkedUploadFileOperation 
extends UploadFileOperation 
{ 
  43     private static final long CHUNK_SIZE 
= 1024000; 
  44     private static final String OC_CHUNKED_HEADER 
= "OC-Chunked"; 
  45     private static final String TAG 
= ChunkedUploadFileOperation
.class.getSimpleName(); 
  47     public ChunkedUploadFileOperation(  Account account
, 
  50                                         boolean forceOverwrite
, 
  53         super(account
, file
, isInstant
, forceOverwrite
, localBehaviour
); 
  57     protected int uploadFile(WebdavClient client
) throws HttpException
, IOException 
{ 
  60         FileChannel channel 
= null
; 
  61         RandomAccessFile raf 
= null
; 
  63             File file 
= new File(getStoragePath()); 
  64             raf 
= new RandomAccessFile(file
, "r"); 
  65             channel 
= raf
.getChannel(); 
  66             mEntity 
= new ChunkFromFileChannelRequestEntity(channel
, getMimeType(), CHUNK_SIZE
, file
); 
  67             ((ProgressiveDataTransferer
)mEntity
).addDatatransferProgressListeners(getDataTransferListeners()); 
  69             String uriPrefix 
= client
.getBaseUri() + WebdavUtils
.encodePath(getRemotePath()) + "-chunking-" + Math
.abs((new Random()).nextInt(9000)+1000) + "-" ; 
  70             long chunkCount 
= (long) Math
.ceil((double)file
.length() / CHUNK_SIZE
); 
  71             for (int chunkIndex 
= 0; chunkIndex 
< chunkCount 
; chunkIndex
++, offset 
+= CHUNK_SIZE
) { 
  72                 if (mPutMethod 
!= null
) { 
  73                     mPutMethod
.releaseConnection();    // let the connection available for other methods 
  75                 mPutMethod 
= new PutMethod(uriPrefix 
+ chunkCount 
+ "-" + chunkIndex
); 
  76                 mPutMethod
.addRequestHeader(OC_CHUNKED_HEADER
, OC_CHUNKED_HEADER
); 
  77                 ((ChunkFromFileChannelRequestEntity
)mEntity
).setOffset(offset
); 
  78                 mPutMethod
.setRequestEntity(mEntity
); 
  79                 status 
= client
.executeMethod(mPutMethod
); 
  80                 client
.exhaustResponse(mPutMethod
.getResponseBodyAsStream()); 
  81                 Log_OC
.d(TAG
, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex 
+ ", count " + chunkCount 
+ ", HTTP result status " + status
); 
  82                 if (!isSuccess(status
)) 
  91             if (mPutMethod 
!= null
) 
  92                 mPutMethod
.releaseConnection();    // let the connection available for other methods