Descargas incompletas de TIdHTTP FileStream
Estoy utilizando TIdHTTP.Get()
para recuperar archivos (potencialmente grandes) en un TFileStream
, básicamente;
filestream := TFileStream.Create(destination, fmCreate);
http.HandleRedirects := True;
try
http.Get(url, filestream);
except
on E: Exception do Memo.Lines.Add(E.Message);
end;
filestream.Free;
Mi problema es cuando el usuario cierra o finaliza el programa mientras se está realizando la descarga. En lugar de mostrar el tamaño del archivo más pequeño de lo que debería ser, el archivo tiene el tamaño de la descarga completada. ¿Por qué ocurre esto?
Utilizo el tamaño del archivo como una comprobación rápida para ver si la descarga fue exitosa, por lo que tener el tamaño correcto pero contenidos incorrectos genera otros errores. No quiero tener que realizar una comprobación de hash para cada archivo, ya que hay muchos, y la comprobación de MD5 lleva mucho tiempo en archivos de varios GB de tamaño.
¿Hay alguna manera de hacer que el tamaño del archivo de destino sea más pequeño si la descarga se interrumpe por cualquier motivo? ¿Alguna forma de no expandir el flujo al tamaño completo a menos que se haya completado toda la descarga correctamente?
davy.ai
La razón por la cual el archivo tiene el tamaño de la descarga completada, incluso si la descarga se interrumpe, es porque el objeto
TFileStream
se crea con la banderafmCreate
. Esta bandera crea un nuevo archivo y trunca cualquier archivo existente a longitud cero si existe. Por lo tanto, aunque la descarga se interrumpa, el tamaño del archivo será el mismo que si la descarga se completara correctamente porque el archivo ya ha sido creado y truncado.Para mitigar este problema, puedes crear el objeto
TFileStream
utilizando la banderafmOpenWrite
en lugar defmCreate
. Esta bandera abre el archivo para escribir, pero preserva los datos existentes en el archivo. Luego, antes de descargar el archivo, puedes usar la propiedadTFileStream.Size
para obtener el tamaño actual del archivo. Después de que la descarga esté completa, puedes comparar el tamaño actual del archivo con el tamaño esperado y eliminar el archivo si no coinciden.Aquí tienes un ejemplo de implementación:
Esta implementación utiliza el método
TIdHTTP.Head()
para obtener el tamaño esperado del archivo antes de la descarga. La propiedadContentLength
del objetoTIdHTTPResponse
devuelto porHead()
contiene el tamaño esperado del archivo, si está disponible.Si el tamaño del archivo no coincide con el tamaño esperado después de la descarga, el archivo se elimina utilizando la función
DeleteFile()
. Esto asegura que el archivo no quede en un estado incompleto o corrupto.Utilizando este enfoque, puedes evitar tener que verificar la integridad de cada archivo mediante el cálculo del hash, al tiempo que te aseguras de que el archivo descargado esté completo y sea correcto.