Posted by bianbian on 2008-01-15 09:00
本文Tags: Delphi, FTP, Indy, 断点续传
Indy不仅支持下载断点续传,也支持上载断点续传,而且不需要对Indy做出改造。
在Blues的blog,他提到可以“通过IDFTP得到服务端已经上传的部分的SIZE,然后通过文件流在本地建立剩余部分的临时文件,然后以APPEND方式上传,传完后删除临时文件,达到上传断点续传的效果”。原文在此:DELPHI ftp 上传断点续传的实现。
我再仔细看了Indy的源码,发现不需要临时文件。可以对Blues的方法作出重大改进:
Put()方法第一个参数可以是TStream(实际上,如果是文件名的话Indy会建立Stream,然后再调用Stream的Put方法)。而且如果Append设为True的话,Indy不会去动Stream的Position:
- procedure TIdFTP.Put(const ASource: TStream; const ADestFile: string = '';
- const AAppend: boolean = false);
- ...
- procedure TIdTCPConnection.WriteStream(AStream: TStream; const AAll: boolean = true;
- const AWriteByteCount: Boolean = False; const ASize: Integer = 0);
- ...
- if AAll then begin //bianbian注:如果Append,AAll是false
- AStream.Position := 0;
- end;
- // This is copied to a local var because accessing .Size is very inefficient
- if ASize = 0 then begin
- LStreamEnd := AStream.Size;
- end else begin
- LStreamEnd := ASize + AStream.Position;
- end;
- LSize := LStreamEnd - AStream.Position;
- ...
也就是说,先把原文件的Stream Seek到Size位置,丢给Indy即可,实现也很简单:
- var
- fs: TFileStream;
- ...
- fs := TFileStream.Create(FullFileName, fmOpenRead or fmShareDenyWrite);
- fs.Seek(size, 0); //偏移
- FTP.Put(fs, ExtractFileName(FullFileName), True);
- fs.Free;
标签:
Delphi,
FTP,
Indy,
断点续传遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | 1 Comment »
Posted by bianbian on 2008-01-13 08:22
本文Tags: Delphi, 运算符
虽然自己写了一个iif函数,还是有问题的:
- function iif(const bool: Boolean; const ifSucc, ifFail: Variant): Variant;
- begin
- if bool then
- Result := ifSucc
- else
- Result := ifFail;
- end;
问题是传进的参数事先是已经被计算出值了,就会导致问题:
1)重复计算。比如:如果bool为真,输出txt,否则在之前加几个空格再输出txt
iif(bool, txt, ' ' + txt);
如果bool为真,按三目运算的规则,' ' + txt 是不会执行到的。不过这里做参数,只能重复计算,效率比if else 低
2)避免不了某些会导致异常的代码
原因还是因为参数会事先计算。比如:如果是目录,输出0,否则输出文件最后修改时间:
iif(Isdir(PathFileName), 0, FileDateToDateTime(FileAge(PathFileName)));
如果PathFileName是目录,FileAge()函数会抛出异常。
按三目运算规则,异常的代码是不应该被执行到的;但这里作参数,一旦是个目录每次必定抛异常,还得改成if else
还没想到好的解决办法,难道用Callbak函数回调?太夸张了点。。。。汗。。。。。
标签:
Delphi,
运算符遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | No Comments »
Posted by bianbian on 2007-08-27 07:05
本文Tags: Tp-Link, 拨号
万恶的南京电信好贵啊,,,,,我的套餐是一个月360小时,2M带宽,168元/月
路由器不可能一直联网,需要手动拨号。不过每次都连上192.168.1.1也太麻烦了。
于是写了个程序自动拨号、断开。程序启动就会连上路由器拨号,关闭的时候会断开连接。

需要的朋友请下载(仅适用于TP-Link路由器):tp_link.zip
标签:
Tp-Link,
拨号遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | No Comments »
Posted by bianbian on 2007-08-17 02:44
本文Tags: Delphi, pipe, 管道, 重定向
虽然是Delphi的,都是调用的WinAPI,C++也可参考。
原理就是管道(Pipe),自己的程序可以Create管道出来,让CreateProcess的子程序能继承自己程序里的管道,替代子程序的标准输入输出。
这样DOS程序对stdout输出的内容就输出到自己程序建立的管道里来了,也就能对其进行读取操作,从而完成重定向到文本框(实时显示)。
基本上Delphi世界里流行的都是DFW上的那个重定向代码,我进行了改进:
1)原来那个代码只能截取输出结果,但是没有换行的整理,要是直接Add到Memo里会杂乱不堪(因为循环取到的内容有可能含有 \r 或 \n,这时候直接Add就有了两行)。
我加上了换行符的处理,Add行的时候按实际的换行进行处理,这样和DOS窗口输出就一致了。
2)原来那个代码没有和Memo绑定,还得自己写Memo操作部分
我加上了Memo作为参数,这样直接调用就省事了。
使用的时候只要 CmdExecAndView(”命令”, memo) 即可。
下面是改进后的代码,欢迎交流:
- procedure CmdExecAndView(FileName: string; memo: TMemo);
- procedure _AddInfo(mmInfo:TMemo; S: string; var line: string);
- var
- i, p: Integer;
- begin
- if mmInfo.Lines.Count > 800 then
- mmInfo.Lines.Clear;
- //去掉 \r
- for i := 0 to Length(S) - 1 do
- if S[i] = #13 then S[i] := ' ';
- line := line + S;
- // \n 断行
- p := Pos(#10, line);
- if p > 0 then
- begin
- // \n 前面的加入一行,后面的留到下次
- mmInfo.Lines.Add(Copy(line, 1, p - 1));
- line := Copy(line, p + 1, Length(line) - p);
- end;
- end;
- var
- hReadPipe, hWritePipe: THandle;
- si: STARTUPINFO;
- lsa: SECURITY_ATTRIBUTES;
- pi: PROCESS_INFORMATION;
- cchReadBuffer: DWORD;
- ph: PChar;
- fname: PChar;
- line: string;
- begin
- fname := allocmem(1024);
- ph := AllocMem(1024);
- lsa.nLength := sizeof(SECURITY_ATTRIBUTES);
- lsa.lpSecurityDescriptor := nil;
- lsa.bInheritHandle := True;
- if CreatePipe(hReadPipe, hWritePipe, @lsa, 0) = false then
- Exit;
- fillchar(si, sizeof(STARTUPINFO), 0);
- si.cb := sizeof(STARTUPINFO);
- si.dwFlags := (STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW);
- si.wShowWindow := SW_HIDE;
- si.hStdOutput := hWritePipe;
- si.hStdError := hWritePipe;
- StrPCopy(fname, FileName);
- if CreateProcess(nil, fname, nil, nil, true, 0, nil, nil, si, pi) = False then
- begin
- FreeMem(ph);
- FreeMem(fname);
- Exit;
- end;
- CloseHandle(hWritePipe);
- while (true) do
- begin
- if not PeekNamedPipe(hReadPipe, ph, 1, @cchReadBuffer, nil, nil) then break;
- if cchReadBuffer <> 0 then
- begin
- if ReadFile(hReadPipe, ph^, 512, cchReadBuffer, nil) = false then break;
- ph[cchReadbuffer] := chr(0);
- _AddInfo(memo, ph, line);
- end
- else if (WaitForSingleObject(pi.hProcess, 0) = WAIT_OBJECT_0) then break;
- Application.ProcessMessages;
- Sleep(200);
- end;
- ph[cchReadBuffer] := chr(0);
- _AddInfo(memo, ph, line);
- CloseHandle(hReadPipe);
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- FreeMem(ph);
- FreeMem(fname);
- end;
标签:
Delphi,
pipe,
管道,
重定向遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | 3 Comments »
Posted by bianbian on 2006-12-22 10:48
本文Tags: Delphi, GUI, IE, 界面
做人要厚道,转载请用链接形式标明出处,谢谢合作。
内嵌IE做软件界面是比较方便和流行的,如.NET 2003的安装程序(好像2005也是,不太记得了)。主要是随便插入图片阿、字体阿什么的。不过因为是内嵌IE,保持了大部分IE的特性,但是这些特性稍不注意,在软件界面看起来却是BUG(或者换句话说,用户很明显地发觉这是个网页…)。比如.NET 2003的安装程序,右键点击会出现IE浏览网页时的右键菜单就是个BUG:

或者呢,按住Shift,点击网页内那些链接,会发现新开了个IE窗口显示,这样连存放的文件名也暴露了。
当然了,BUG还不仅如此:虽然这个主要的内嵌IE不支持文件拖入(会显示禁止drop的图标),但是安装时右上角不停变化的图片处其实也是个内嵌IE——这里Microsoft显然遗漏了禁止drop的处理——你用鼠标拖个htm文件过去,会发现是可以drop的(直接用PrintScreen截的,没有鼠标,不过能看到拖过去的htm图标),如图:

那么针对这些问题,我说一下用内嵌IE做软件界面的几点体会:
(1)避免script error。(今天没有空,内容待补充,下同)
(2)去掉右键菜单。
(3)禁止拖入。
(4)禁止打开新窗口。
(5)往内嵌IE里写入数据。
(6)截获页面跳转执行相应的代码,换句话说就是和主程序交互。
(7)这点可能是Delphi 7特有的bug,Delphi自带的TWebBrowser不支持键盘:如回车键提交表单等。
标签:
Delphi,
GUI,
IE,
界面遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | 2 Comments »
Posted by bianbian on 2006-09-16 03:28
本文Tags: Delphi, ShellAPI
- var
- S: string;
- T: TSHFileOpStruct;
- begin
- S := '目录名';
- with T do
- begin
- Wnd := 0;
- wFunc := FO_DELETE;
- pFrom := PChar(S);
- pTo := nil;
- fFlags := FOF_ALLOWUNDO + FOF_NOCONFIRMATION + FOF_NOERRORUI;
- //标志表明允许恢复,无须确认并不显示出错信息
- hNameMappings := nil;
- lpszProgressTitle := '正在删除文件夹';
- fAnyOperationsAborted := False;
- end;
- SHFileOperation(T);
- end;
标签:
Delphi,
ShellAPI遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Delphi, Technology | No Comments »