Why the value of size is zero?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
candid_1120
Earned some good credits
Earned some good credits
Posts: 118
Joined: Sun Aug 28, 2005 8:42 am

Why the value of size is zero?

Post by candid_1120 »

Code: Select all

static const wxString directory = _T("update");
static const wxString filename = _T("update.zip");
wxPuts(_T("*** Begining wxFTP download ***\n"));
ftp.ChDir(directory);
   if(!ftp.FileExists(filename)) return;
       //Set download mode
	ftp.SetBinary();
	
    wxInputStream *in = ftp.GetInputStream(filename);
    if ( !in )
    {
        wxPrintf(_T("ERROR: couldn't get input stream for %s\n"), filename);
    }
    else
    {
        long int size = in->GetSize(); 
I have allready login in the sever,try to download the file(update.zip) from the server,but how to download?The value of size is zero all the time
leio
Can't get richer than this
Can't get richer than this
Posts: 802
Joined: Mon Dec 27, 2004 10:46 am
Location: Estonia, Tallinn
Contact:

Post by leio »

wxStreamBase::GetSize manual says:

"Warning

There are streams which do not have size by definition, such as socket streams. In that cases, GetSize returns 0 so you should always test its return value."

You seem to be dealing with a socket stream.
Compilers: gcc-3.3.6, gcc-3.4.5, gcc-4.0.2, gcc-4.1.0 and MSVC6
OS's: Gentoo Linux, WinXP; WX: CVS HEAD

Project Manager of wxMUD - http://wxmud.sf.net/
Developer of wxGTK;
gtk+ port maintainer of OMGUI - http://www.omgui.org/
upCASE
Moderator
Moderator
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE »

Did you try with wxFTP::GetFileSize() instead?
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda
candid_1120
Earned some good credits
Earned some good credits
Posts: 118
Joined: Sun Aug 28, 2005 8:42 am

Post by candid_1120 »

Yes I had try it,but the value of size isn't the real size of file which I want to download
upCASE
Moderator
Moderator
Posts: 3176
Joined: Mon Aug 30, 2004 6:55 am
Location: Germany, Cologne

Post by upCASE »

Hmm, you're right. The docs say
Returns the file size in bytes or -1 if the file doesn't exist or the size couldn't be determined. Notice that this size can be approximative size only and shouldn't be used for allocating the buffer in which the remote file is copied, for example.
OS: OpenSuSE, Ubuntu, Win XP Pro
wx: svn
Compiler: gcc 4.5.1, VC 2008, eVC 4

"If it was hard to write it should be hard to read..." - the unknown coder
"Try not! Do. Or do not. There is no try." - Yoda
candid_1120
Earned some good credits
Earned some good credits
Posts: 118
Joined: Sun Aug 28, 2005 8:42 am

Post by candid_1120 »

Can you give me a example of the wxFTP about download the file on the server,thanks
Lead
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Mar 17, 2006 12:24 am
Location: Clearwater FL

Post by Lead »

I've been trying to get wxFTP to work so I can download files from an FTP server but I'm running into the same problem, and searching this board and the docs is not giving me a fast solution.

Can wxFTP::GetFileSize() or wxInputStream::GetSize() be fixed?

I even tried sending the FTP "SIZE" command to the server (via wxFTP::SendCommand) but it returns the same result. For example: I'm testing the download of a 227k file and by using a wxInputStream::GetC loop (as shown in several other posts) I get the file but it takes about 10 seconds. If I force the size for wxInputStream::Read to the file's actual size the file downloads almost instantly. Since the size of the file downloads are dynamic is there any way to test for the size successfully? Using GetC() is so slow and downloading 100MB of data is going to be like dial-up again :(
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

instead of using GetC() to read single bytes, use wxInputStream::Read(void *buffer, size_t size) to load data in a big buffer and wxInputStream::LastRead() or wxInputStream::Eof() to check if the transfer is finished.

With FTP or HTTP downloads you can never guarantee to know the filesize in advance.
Use the source, Luke!
Lead
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Mar 17, 2006 12:24 am
Location: Clearwater FL

Post by Lead »

Okay, I've gotten it that far and have the data in the buffer but can't save it to disk. I've also tried displaying the buffer to the screen but haven't had luck there either. I think because it reads the size wrong when it loads the buffer it has no data, but I can't verify that. Can you load the buffer without specifying a size? Just go until EOF?

How do I take the data in the buffer and save it to a file of the same name that was downloaded? Attempts with wxFFile::Write and wxFile::Write get me as far as an empty file of that name. I know I'm missing something somewhere but can't find it. Any direction would be greatly appreciated.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

here's a small code-snippet, it downloads a page using wxURL, but the wxInputStream part is the same as with wxFTP, so i guess you can use it for a start:

Code: Select all

#define BUFSIZE 8192
wxURL url(wxT("http://www.wxwindows.org/manuals/2.6.3/wx_contents.html"));
if(url.GetError()==wxURL_NOERR)   {
  wxFile outfile(wxT("d:\\wx_contents.html"), wxFile::write);
  wxInputStream *in_stream = url.GetInputStream();
  unsigned char buffer[BUFSIZE];
  do {
    in_stream->Read(buffer, BUFSIZE);
    size_t bytes_read=in_stream->LastRead();
    if(bytes_read>0) outfile.Write(buffer, bytes_read);
  } while( !in_stream->Eof() );
  delete in_stream;
  outfile.Close();
}
Use the source, Luke!
Lead
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Mar 17, 2006 12:24 am
Location: Clearwater FL

Post by Lead »

I played around with that code but it locked up my machine. Best guess is that the last read of the buffer did not fill it, so when it went to write it just hung up. That's the problem I've been having.

So, I tried this variant, mostly from other posts...

Code: Select all

     wxInputStream* ftpIn = ftp.GetInputStream(filename);
     if (ftpIn)
     {
          file.Open(filename,wxFile::write);

          // this code works but is SLOW!
          wxString buffer;
          wxString oneChar;
          oneChar = ftpIn->GetC();
          buffer += oneChar;

          while ( (ftpIn->LastRead()) > 0 )
          {
               oneChar = ftpIn->GetC();
               buffer += oneChar;
          };

          file.Write(buffer, buffer.size() );
          file.Close();
     }
This way the size for the write is correct and the file is saved. It takes roughly 10 seconds for the 222kb file to be pulled from an FTP server running on my own machine (127.0.0.1) one character at a time. Using FTP from the command prompt is an immediate transfer. I was hoping someone had solved dynamically getting the filesize using GetSize() or some other creative means.

Everything appears to hinge on giving a valid size for the Read(). A size larger than the file seems to cause it to hang also. I'll have to try that again to be sure.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax »

trying to read too many bytes should not hang the application. This works perfectly fine with wxURL or other streams, maybe wxFTP behaves differently.

Maybe you should switch to libcurl or wxCURL.
Use the source, Luke!
Post Reply