Getting FileSize before InputStream
I want to create a progressBar for an FTP download. The server where I am downloading the file has all of its directories and files hidden. I want to display the progress of the download. Is there any way I can get the file size? Here is my current code:
FTPclient = new FTPClient();
FTPclient.setListHiddenFiles(true);
FTPclient.connect(hostPart);
FTPclient.login(userName, passWord);
FTPclient.setFileType(FTP.BINARY_FILE_TYPE);
InputStream instream = FTPclient.retrieveFileStream(pathExcludingHostIncludingFirstSlash);
int l;
byte[] tmp = new byte[2048];
int updateCounter = 0;
int bytesDownl开发者_如何学Coaded = 0;
while ((l = instream.read(tmp)) != -1) {
fos.write(tmp, 0, l);
bytesDownloaded+=2048;
updateCounter++;
if(updateCounter==3){
kilobytesDownloaded=(bytesDownloaded / 1024);
publishProgress((String[])null);
updateCounter=0;
}
There's no way to do this reliably across all FTP services.
The FTP protocol does not provide a way to get file sizes, so you would need to resort to requesting a directory listing and unpicking the (server specific) text that you get back. Furthermore, there is no guarantee that directory listing will be enabled, or that you will have permission to list the directory.
Having said this, some FTP libraries can be configured to attempt to get a file size. For example, with the Apache FTPClient library you can (try to) use the listFiles(String)
method and look at the resulting FTPFile
object.
EDIT
@Kevin Brock mentions the FTP SIZE command as a possibility.
- This is command was first defined in RFC 3659 in 2007. A lot of deployed FTP server software is much older than that.
- SIZE is an optional command; i.e. even RFC 3659 compliant servers are not required to support it.
- Even if SIZE is supported by a server, the current Apache FTPClient APIs do not include a method for getting the size of a file (apart from via
listFiles
). Of course, this may change in the future. - The ftp4j
FTPClient
class apparently does implement SIZE and make it available via itsfileSize(...)
method.
I haven't found a simple command to do this either. My solution was to call the skip command, which should return the number of bytes skipped. Sum this until skip returns 0. There is a possibility that skip can return 0 for reasons other than end of file, but in the field it seems to work well.
Here is some example code:
InputStream checkStream = m_ftpClient.retrieveFileStream(name);
long fileLength = 0;
long transferredLength = 0;
do
{
transferredLength = checkStream.skip(MAX_BYTES);
fileLength += transferredLength;
}while(transferredLength > 0);
精彩评论