问题遇到的现象和发生背景
我在使用Delphi11.1的时候,想使用TIdHttp组件来达到从网络中用多线程下载的目的。【这里是Delphi!!】
现在有个很严重的问题!我无法获取网络中的文件大小。
我试过,如果用小文件下载是非常可以的!比如说我从网上下载一个100KB的文件,就非常可以下载。但是当我从python官网中下载一个install安装包的时候,这个安装包有27多MB,然后就会报错,报错位置就是出在获取文件大小这一部分。
我的代码是这里的。http://www.360doc.com/content/10/0818/13/2071424_46919572.shtml
然后,就没办法获取文件大小。出的错误在这里:
问题相关代码,请勿粘贴截图
我的代码都是看了这上面的帖子写的!https://wenku.baidu.com/view/14617e36e%F0%9F%90%8Eefdc8d376e%F0%9F%90%8Ee3242.html
unit UnzipMethod;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient,
IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze,
IdThreadComponent, IdFTP;
type
TThread1 = class(TThread)
private
fCount, tstart, tlast: integer;
tURL, tFile, temFileName: string;
tResume: Boolean;
tStream: TFileStream;
protected
procedure Execute; override;
public
constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count,start, last: integer);
procedure DownLoadFile(); //下载文件
end;
type
TForm1 = class(TForm)
IdAntiFreeze1: TIdAntiFreeze;
IdHTTP1: TIdHTTP;
Button1: TButton;
ProgressBar1: TProgressBar;
IdThreadComponent1: TIdThreadComponent;
Label1: TLabel;
Label2: TLabel;
ListBox1: TListBox;
Edit1: TEdit;
Edit2: TEdit;
Label3: TLabel;
Label4: TLabel;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure IdHttp1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
procedure IdHttp1Work(Sender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
procedure Button2Click(Sender: TObject);
procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
procedure Button3Click(Sender: TObject);
private
public
nn, aFileSize, avg: Integer;
MyThread: array[1..256] of TThread;
procedure GetThread();
procedure AddFile();
function GetURLFileName(aURL: String): String;
function GetFileSize(aURL: String): Integer;
end;
var
Form1: TForm1;
implementation
var
AbortTransfer: Boolean;
aURL, aFile: String;
tcount: Integer;
{$R *.dfm}
//接收文件
function TForm1.GetURLFileName(aURL: string): string;
var
i: integer;
s: string;
begin //返回下载地址的文件名
s := aURL;
i := Pos('/', s);
while i <> 0 do //去掉"/"前面的内容剩下的就是文件名了
begin
Delete(s, 1, i);
i := Pos('/', s);
end;
Result := s;
end;
//得到文件大小
function TForm1.GetFileSize(aURL: string): integer;//**********************错误就发生在这里********************
var
FileSize: integer;
begin
IdHTTP1.Head(aURL);
FileSize := IdHTTP1.Response.ContentLength;
IdHttp1.Disconnect;
Result := FileSize;
//messagebox(Handle, pchar(inttostr(FileSize)), '', 0);
end;
//多线程下载
procedure TForm1.Button1Click(Sender: TObject);
var
j: integer;
begin
Form1.ListBox1.Clear;
Form1.ProgressBar1.Position := 0;
tcount := 0;
Showmessage('OK!主线程在执行,获得文件名并显示在Edit5中');
aURL := Edit1.Text; //下载地址
aFile := GetURLFileName(Edit1.Text); //得到文件名
nn := StrToInt(Edit2.Text); //线程数
j := 1;
aFileSize := GetFileSize(aURL);
avg := trunc(aFileSize / nn);
try
GetThread();
while j <= nn do
begin
MyThread[j].Resume; //唤醒线程
j := j + 1;
end;
except
Showmessage('创建线程失败!');
Exit;
end;
end;
//开始下载前,将ProgressBar1的最大值设置为需要接收的数据大小.*******************
procedure TForm1.IdHttp1WorkBegin(Sender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
AbortTransfer := False;
ProgressBar1.Max := AWorkCountMax;
ProgressBar1.Min := 0;
ProgressBar1.Position := 0;
end;
//接收数据的时候,进度将在ProgressBar1显示出来。
procedure TForm1.IdHttp1Work(Sender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
if AbortTransfer then
begin
IdHttp1.Disconnect;//中断下载
end;
ProgressBar1.Position := AWorkCount;
//ProgressBar1.Position := ProgressBar1.Position + AWorkCount;//*******显示速度极快
Application.ProcessMessages;//这样使用不知道对不对
end;
//中断下载
procedure TForm1.Button2Click(Sender: TObject);
begin
AbortTransfer := false;
IdHttp1.Disconnect;
end;
//状态显示
procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
begin
ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText);
end;
//退出程序
procedure TForm1.Button3Click(Sender: TObject);
begin
Application.Terminate;
end;
//循环产生线程
procedure TForm1.GetThread();
var
i: integer;
start, last: array[1..256] of Integer;
FileName: String;
begin
i := 1;
while i <= nn do
begin
start[i] := avg * (i - 1);
last[i] := avg * i - 1;//这里原先时last := avg * i
if i = nn then
begin
last[i] := avg * i + aFileSize - avg * nn;//这里原先时aFileSize
end;
fileName := aFile + inttostr(i);
MyThread[i] := TThread1.create1(aURL, aFile, fileName, false, i, start[i], last[i]);
i := i + 1;
end;
end;
procedure TForm1.AddFile();//合并文件
var
mStream1, mStream2: TMemoryStream;
i: Integer;
begin
i := 1;
mStream1 := TMemoryStream.Create;
mStream2 := TMemoryStream.Create;
mStream1.LoadFromFile(aFile + '1');
while i < nn do
begin
mStream2.LoadFromFile(aFile + inttostr(i + 1));
mStream1.Seek(mStream1.size, soFromBeginning);
mStream1.CopyFrom(mStream2, mStream2.size);
mStream2.Clear;
i := i + 1;
end;
mStream2.Free;
mStream1.SaveToFile(aFile);
mStream1.Free;
//删除临时文件
i := 1;
while i <= nn do
begin
deleteFile(aFile + inttostr(i));
i := i + 1;
end;
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下载成功');
end;
//构造函数
constructor TThread1.create1(aURL, aFile, FileName: String; bResume: Boolean; Count, start, last: integer);
begin
inherited create(true);
FreeOnTerminate := true;
tURL := aURL;
tFile := aFile;
fCount := Count;
tResume := bResume;
tstart := start;
tlast := last;
temFileName:= FileName;
end;
//下载文件函数
procedure TThread1.DownLoadFile();
var
temHttp: TIdHTTP;
begin
temHttp := TIdHTTP.Create(nil);
temHttp.OnWorkBegin := Form1.IdHttp1WorkBegin;
temHttp.OnWork := Form1.IdHttp1Work;
temHttp.OnStatus := Form1.IdHttp1Status;
Form1.IdAntiFreeze1.OnlyWhenIdle := False;//设置使程序有反应
if FileExists(temFileName) then //如果文件已经存在
tStream := TFileStream.Create(temFileName, fmOpenWrite)
else
tStream := TFileStream.Create(temFileName, fmCreate);
if tResume then //续传方式
begin
exit;
end
else //覆盖或新建方式
begin
temHttp.Request.ContentRangeStart := tstart;
temHttp.Request.ContentRangeEnd := tlast;
end;
try //开始下载
//TIdFTP1.Get(temFileName,tStream,true); //开始下载
temHttp.Get(tURL,tStream); //开始下载
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName + 'download');
finally
FreeAndNil(tStream);
temHttp.Disconnect;
end;
end;
procedure TThread1.Execute;
begin
if Form1.Edit1.Text <> '' then
DownLoadFile
else
exit;
inc(tcount);
if tcount = Form1.nn then
begin
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合并下载文件!');
Form1.AddFile;
end;
end;
end.
运行结果及报错内容
第一次在$770FED42遇到异常.异常类 EIdOSSLUnderlyingCryptoError,消息
'Error connecting with SSL.
error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version'.
进程Test.exe (3844)
我的解答思路和尝试过的方法
尝试过使用FTP下载,但也没有用……FTP始终是用不习惯。很多方法都没有
我想要达到的结果
能够使文件部分正确获取到文件大小。哪怕遇到稍大的文件也可以。