Utilizo socket para isso, mas utilizo um protocolo para enviar o arquivo em blocos e ainda em paralelo porque do lado servidor defino uma quantidade parametrizável de threads para receber o arquivo caso não tenha recebido.
Tambem consigo parametrizar o tamanho dos blocos porque conforme a rede tenho que enviar blocos maiores, em outras, blocos menores.
Como recebo arquivo que não pode ser perdido, utilizo checksum para conferir se realmente o recebi completo antes de enviar um comando para o host apagar a origem.
Se você trabalha com muitos arquivos grandes, utiliza a Internet e quer desempenho, o método mais rápido de todos é o UDP + protocolo proprietário capaz de conferir ao final quais foram os blocos não recebidos para então pedir os blocos e concluir a transferência. Esta forma é a mais rápida de todas e se você quiser segurança, pode criptografar o arquivo. Se sua informação não for ultra-secreta, nem precisa fazer isso, somente autentique a conexão para saber se o host é realmente conhecido.
A segunda opção mais rápida é fazer um protocolo proprietário utilizando socket.
O webservice é semelhante ao socket, mas acredito que você terá um desempenho menor porque já envolverá camadas WS e isso aumenta o overhead.
A aplicação de TLS ou SSL é uma forma de autenticar o host e blindar o túnel por onde os dados trafegarão, acho que é excelente aplicar isso no seu projeto, mas eu nunca passei dos testes nesta questão, só fiz testes mesmo porque esbarrei num problema de pouco tempo de projeto e não pude seguir nesta linha para criar uma fábrica de chaves, pré-autenticação do host que ainda não tem chave, distribuição de chave até conseguir estabelecer de uma vez uma conexão TLS ou SSL com o host. Isso requer um projeto secundário, porque você precisa ter dois serversockets no ar, uma para autenticar o host sem SSL ou TLS e então gerar as chaves, o outro serversocket já usa TLS e SSL para aceitar conexão de host com sua chave.
wiliamps