“Make things as simple as possible, but not simpler.”
It's good when you start your program simple and then gradually extend it.
Big projects always begin with something, and with the agile approach I think you're on the right track.
One thing you should make sure of is that you don't depend on the initial simplicity.
Let's have a look at your example.
1) Try to make the program able to transfer 1 file
2) Try to make the transfer into a queue
3) Try to implement multi-threading
During the second iteration, you will be designing the most important classes for the program.
You will be creating abstractions for the files, probably re-doing basic server abstraction from the first iteration, and the transfer manager itself. You will also have to create some kind of GUI that allows to work with multiple files, and tie this frontend with the backend.
After this stage, changing basic API will be hard. Because of that, make sure that you won't have to redesign the whole system at the third iteration. When doing second iteration design, keep things simple and flexible enough (you're in luck when you know what is going to be changed but this is not always the case).
On the practical note, this usually means reducing dependencies with Inversion of Control pattern, interacting with the backend (and inside the backend, too) using interfaces, and separating different pieces of logic into independent modules which can later easily be replaced.