Interface to the drive:
SATA is faster than PATA. USB3 is faster than USB2. USB3 should give well over 100 MB/s.
Type of file system. NTFS is probably slower than FAT32 as it is a journalising file system (although FAT32 has a 4 GB limit on a single file).
RAM and bus speed.
CPU is relatively unimportant as transferring files between drives should be DMA not CPU dependent for performance.
Operating System's disk access scheduling algorithms. Important for small files. Good algorithms minimise seek times on HDDs. Each seek is wasted time. This is not relevant on SSDs.
For HDDs, using the correct sector interleave factor. Not relevant for SSDs.
For HDDs, the drive's ability to schedule writes to the media from its own cache to optimise write performance.
Transfer block size. Easiest to see in Linux. It takes much longer to copy files using 512 reads/writes than it does using 1 MB transfers.
For SSDs, have transfers aligned to the drive's internal block size (often aligned to 4 kB boundaries).
For HDDs, having the drive defragmented, and where possible using the outer (lowest numbered) cylinders which have much higher transfer speeds than the inner cylinders. Where a drive carries multiple file systems, the rarely used files should be on file systems closest to the centre on the disk.
Using high speed HDDs. The rotational latency of a 10000 rpm drive is about a third of the latency of a 3600 rpm drive. (5400 and 7200 rpm are probably the most common speeds.)
If the files are being compressed, encrypted or scanned for malware, then this can be CPU intensive.
RAID hardware may help compared with single disks. RAID 0 (striping) will normally offer best performance with read/write blocks that match the stripe width. RAID 1 can be significantly slower at writing but faster at reading. RAID 3 or 5 can offer some speed advantages providing the parity generation in the RAID is not a limiting factor while writing.
I hope this helps.