PDA

Ver la Versión Completa : Descargar fichero 25 Mb desde internet


fmatias
03-07-2007, 10:21:38
Hola a todos,
Quiero crear una aplicación que descargue un fichero desde internet similar a la descarga desde cualquier navegador. Con la siguiente función que os indico realiza el proceso, pero va muy lento y se queda colgado cuando lleva un 10% aprox.
Respecto a la velocidad, he realizado varias pruebas desde distintos navegadores y todos van hasta 10 veces más rápido.

Podríais ayudarme a depurarlo mejor?

function TForm1.Bajar(Url: string; Archivo: string): Boolean;
var
hFile: THandle;
hNet: HINTERNET;
hUrl: HINTERNET;
Buffer: array[0..10240] of Char;
BytesRead: DWORD;
BytesWritten: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(Archivo), GENERIC_WRITE, 0, nil, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
if (hFile <> INVALID_HANDLE_VALUE) then
begin
hNet := InternetOpen('agent', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if (hNet <> nil) then
begin
hUrl := InternetOpenUrl(hNet, PChar(Url), nil, 0,
INTERNET_FLAG_RELOAD, 0);
if (hUrl <> nil) then
begin
while (InternetReadFile(hUrl, @Buffer, sizeof(Buffer), BytesRead)) do
begin
// Añadir la siguiente liena si es necesario
Application.ProcessMessages;
if (BytesRead = 0) then
begin
Result := TRUE;
break;
end;
if (not WriteFile(hFile, Buffer, BytesRead, BytesWritten, nil)) then
break;
if (BytesRead <> BytesWritten) then
break;
end;
InternetCloseHandle(hUrl);
end;
InternetCloseHandle(hNet);
end;
CloseHandle(hFile);
end;
end;

Muchas gracias
F.Matías.

phrodo
03-07-2007, 10:49:10
¿por que no pruebas con el componente IDHttp de las Indy?

Es muy facil con ese componente bajar cualquier fichero desde tu propia aplicación

Este codigo lo utilizo yo en una aplicación mia. Espero que te sirva. Yo lo importé de un colega del foro, y funcionó a la perfección. La direccion URL de descarga la tienes que cambiar por la direccion del fichero que quieras descargar.



resourcestring

rsFinDescarga = 'Fin de la descarga';
rsProgresoDes = 'Progreso descarga %d / %d KB';
rsUrlDescarga = 'http://www.tudireccion.com/tuarchivo.rar';

procedure TFPpal.btnDescargaClick(Sender: TObject);
begin
btnDescarga.Enabled := false;
try
IdHTTP.Get(rsUrlDescarga);
finally
btnDescarga.Enabled := true;
end;
ShowMessage(rsFinDescarga);
end;

procedure TfrmPrincipal.IdHTTPWorkBegin(Sender: TObject;
AWorkMode: TWorkMode; const AWorkCountMax: Integer);
begin
FTotalBytes := AWorkCountMax;
bProgreso.Max := AWorkCountMax;
gProgreso.MaxValue := AWorkCountMax;
end;

procedure TfrmPrincipal.IdHTTPWork(Sender: TObject;
AWorkMode: TWorkMode; const AWorkCount: Integer);
begin
Application.ProcessMessages();
gProgreso.Progress := AWorkCount;
bProgreso.Position := AWorkCount;

lbProgresoDescarga.Caption := Format
(rsProgresoDes, [AWorkCount div 1024,
FTotalBytes div 1024]);
end;

procedure TfrmPrincipal.IdHTTPWorkEnd(Sender: TObject;
AWorkMode: TWorkMode);
begin
gProgreso.Progress := 0;
bProgreso.Position := 0;

lbProgresoDescarga.Caption :=
Format(rsProgresoDes, [0,0]);
end;




espero que te sirva. Un saludo.

fmatias
03-07-2007, 11:54:23
Muchas graciasphrodopor contestar tan rápido.

acabo de trabajar con el script que me has enviado y realiza el proceso de descarga correctamente y a buena velocidad.

El problema que detecté al leer el código y una vez probado es que no sé donde guarda el fichero descargado.

He realizado una busqueda en todod el disco y no aparece.

¿Falta aún procedimiento? No he trabajado nunca con las Indys y realmente no sé como funcionan los componentes.

Gracias nuevamente.

fmatias
03-07-2007, 12:55:14
Bueno, ya he corregido el procedimiento para que se guarde el fichero en local en la dirección indicada.

El procedimiento que me indicó prhodo fue el siguiente:
procedure TFPpal.btnDescargaClick(Sender: TObject);
begin
btnDescarga.Enabled := false;
try
IdHTTP.Get(rsUrlDescarga);
finally
btnDescarga.Enabled := true;
end;
ShowMessage(rsFinDescarga);
end;


Para que guarde el fichero lo he modificado de la siguiente forma, añadiendo la variable Destino y modificando la función IdHttp.get


procedure TForm1.btndescargaClick(Sender: TObject);
var
Destino: TFileStream;
begin
btnDescarga.Enabled := false;
Destino:=TFileStream.Create('c:\destino.zip', fmCreate);

try
IdHTTP.Get(ecarga.Text,destino);
finally
btnDescarga.Enabled := true;
destino.free;
end;
ShowMessage(rsFinDescarga);

end;

Muchas gracias a prhodo por su colaboración, me ha ahorrado bastante tiempo de trabajo.

Saludos a todos.

phrodo
06-07-2007, 17:43:59
De nada hombre... es la primera vez que ayudo a alguien del foro (creo)... y la verdad es que sienta muy bien ;)

Está muy bien la solución que le has incorporado. Si me permites proponerte na solución más elegante, sería abrir una ventana de destino (de las que hay en la pestaña "dialogs" de delphi, para que el usuario elija donde desea guardar el archivo.

Luego simplemente le pasas el destino que haya escogido, al FileStream.

un saludo,