Posted by bianbian on 2008-06-19 08:08
本文Tags: bug, FTP, ftp4j, 解决
上次推荐的ftp4j在解析部分FTP站点的目录list的时候遇到了FTPListParseException(也怪FTP协议没有对LIST格式作出标准)。查看源码发现,主要是两个问题:
1)文件权限不只rwx这三个,附加了s、t(详见http://en.wikipedia.org/wiki/File_system_permissions)
2)部分ftpd似乎直接调用的“ls -l”输出目录,第一行是“total xxx”
给作者写信了,说不定下个版本就有Sepcial Thanks to bianbian 了。嘿嘿嘿嘿。。。
修正后的代码(省略后面没有变化的部分):
- public class UnixListParser implements FTPListParser {
- // bianbian.org: Pattern有问题,修正
- private static final Pattern PATTERN = Pattern
- .compile("^([dlcbsp\\-])[r\\-][w\\-][xsS\\-][r\\-][w\\-][xsS\\-][r\\-][w\\-][xtT\\-]\\s+"
- + "(?:\\d+\\s+)?\\S+\\s*\\S+\\s+(\\d+)\\s+(?:(\\w{3})\\s+(\\d{1,2}))\\s+"
- + "(?:(\\d{4})|(?:(\\d{1,2}):(\\d{1,2})))\\s+"
- + "([^\\\\/*?\"<>|]+)(?: -> ([^\\\\*?\"<>|]+))?$");
- private static final DateFormat DATE_FORMAT = new SimpleDateFormat(
- "MMM dd yyyy HH:mm", Locale.US);
- public FTPFile[] parse(String[] lines) throws FTPListParseException {
- int currentYear = new GregorianCalendar().get(Calendar.YEAR);
- int i, jump = 0, size = lines.length;
- //bianbian.org: glftpd 的第一行和 ls -l 一样,会丢个"total N"过来,先去掉
- if (size > 0 && lines[0].startsWith("total")) {
- size--;
- jump = 1;
- }
- FTPFile[] ret = new FTPFile[size];
- for (i = 0; i < size; i++) {
- Matcher m = PATTERN.matcher(lines[i + jump]);
- if (m.matches()) {
- ret[i] = new FTPFile();
- // Retrieve the data.
- char typeChar = m.group(1).charAt(0);
- String sizeString = m.group(2);
- String monthString = m.group(3);
- String dayString = m.group(4);
- String yearString = m.group(5);
- String hourString = m.group(6);
- String minuteString = m.group(7);
- String nameString = m.group(8);
- String linkedString = m.group(9);
- // Parse the data.
- if ("-cbsp".indexOf(typeChar) > -1) {
- ret[i].setType(FTPFile.TYPE_FILE);
- } else if (typeChar == 'd') {
- ret[i].setType(FTPFile.TYPE_DIRECTORY);
- } else if (typeChar == 'l') {
- ret[i].setType(FTPFile.TYPE_LINK);
- ret[i].setLink(linkedString);
- } else {
- throw new FTPListParseException();
- }
- ...
标签:
bug,
FTP,
ftp4j,
解决遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Java, Technology | 3 Comments »
Posted by bianbian on 2008-04-15 11:08
本文Tags: FTP, ftp4j, FTPClient
ftp4j是个很年轻的开源项目,但是试用后发现很好很强大,如果你找一个纯java的FTP库,要支持socks4,socks4a,socks5,http代理,就是他了!
比apache的FTPClient(不支持代理)、半商业的edtFTPj(PRO支持代理,但是要$,而且是系统变量级的代理,不能单个指定)等好用多了,而且是LGPL协议,源码质量很高。(不过如果你需要FTPS及SFTP,那ftp4j不支持)
jar包只有50多k,地址在这里:ftp4j
使用代理的代码:
- import java.util.ArrayList;
- import it.sauronsoftware.ftp4j.FTPClient;
- import it.sauronsoftware.ftp4j.FTPFile;
- import it.sauronsoftware.ftp4j.connectors.SOCKS4Connector;
- ......
- //ftp4j使用socks4代理连接FTP示例,by http://bianbian.org
- FTPClient ftp = new FTPClient();
- SOCKS4Connector socks4 = new SOCKS4Connector("127.0.0.1", 1080);
- ftp.setConnector(socks4);
- ftp.connect("an.ip.or.host", 21);
- ftp.login("anonymous", "bianbian@bianbian.org");
- ftp.setCharset("gbk");
- //list files
- FTPFile[] list = ftp.list();
- for(FTPFile file : list) {
- System.out.println(file);
- }
- ftp.disconnect(true);
标签:
FTP,
ftp4j,
FTPClient遵守创作共用协议,转载请链接形式注明来自
http://bianbian.org 做人要厚道
相关日志
Posted in Java, Technology | 2 Comments »
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 »