最近有个项目用到ftp上传,然后我在github上面找了一个叫android-upload-service的库,一开始连接的是家里NAS上的ftp没有问题,后来部署了服务器,无论是pureftp还是vsftp死活连接不上,有点坑,于是把源码拉下来看了一下,它是封装了Apache的Commons Net库,debug进去发现FTPUploadTask里面的ftpClient在调用connect之后就报超时异常,看样子是配置问题,经过逐一排查,发现是ftpClient.setAutodetectUTF8(true)导致,直接注销掉就行了,FTPUploadTask的upload函数如下
@Override
protected void upload() throws Exception {
try {
if (ftpParams.useSSL) {
String secureProtocol = ftpParams.secureSocketProtocol;
if (secureProtocol == null || secureProtocol.isEmpty())
secureProtocol = FTPUploadTaskParameters.DEFAULT_SECURE_SOCKET_PROTOCOL;
ftpClient = new FTPSClient(secureProtocol, ftpParams.implicitSecurity);
Logger.debug(LOG_TAG, "Created FTP over SSL (FTPS) client with "
+ secureProtocol + " protocol and "
+ (ftpParams.implicitSecurity ? "implicit security" : "explicit security"));
} else {
ftpClient = new FTPClient();
}
ftpClient.setBufferSize(UploadService.BUFFER_SIZE);
ftpClient.setCopyStreamListener(this);
ftpClient.setDefaultTimeout(ftpParams.connectTimeout);
ftpClient.setConnectTimeout(ftpParams.connectTimeout);
ftpClient.setAutodetectUTF8(true);//注销掉这一行
Logger.debug(LOG_TAG, "Connect timeout set to " + ftpParams.connectTimeout + "ms");
Logger.debug(LOG_TAG, "Connecting to " + params.serverUrl
+ ":" + ftpParams.port + " as " + ftpParams.username);
ftpClient.connect(params.serverUrl, ftpParams.port);
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
throw new Exception("Can't connect to " + params.serverUrl
+ ":" + ftpParams.port
+ ". The server response is: " + ftpClient.getReplyString());
}
if (!ftpClient.login(ftpParams.username, ftpParams.password)) {
throw new Exception("Error while performing login on " + params.serverUrl
+ ":" + ftpParams.port
+ " with username: " + ftpParams.username
+ ". Check your credentials and try again.");
}
// to prevent the socket timeout on the control socket during file transfer,
// set the control keep alive timeout to a half of the socket timeout
int controlKeepAliveTimeout = ftpParams.socketTimeout / 2 / 1000;
ftpClient.setSoTimeout(ftpParams.socketTimeout);
ftpClient.setControlKeepAliveTimeout(controlKeepAliveTimeout);
ftpClient.setControlKeepAliveReplyTimeout(controlKeepAliveTimeout * 1000);
Logger.debug(LOG_TAG, "Socket timeout set to " + ftpParams.socketTimeout
+ "ms. Enabled control keep alive every " + controlKeepAliveTimeout + "s");
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.setFileTransferMode(ftpParams.compressedFileTransfer ?
FTP.COMPRESSED_TRANSFER_MODE : FTP.STREAM_TRANSFER_MODE);
// this is needed to calculate the total bytes and the uploaded bytes, because if the
// request fails, the upload method will be called again
// (until max retries is reached) to retry the upload, so it's necessary to
// know at which status we left, to be able to properly notify firther progress.
calculateUploadedAndTotalBytes();
String baseWorkingDir = ftpClient.printWorkingDirectory();
Logger.debug(LOG_TAG, "FTP default working directory is: " + baseWorkingDir);
Iterator<UploadFile> iterator = new ArrayList<>(params.files).iterator();
while (iterator.hasNext()) {
UploadFile file = iterator.next();
if (!shouldContinue)
break;
uploadFile(baseWorkingDir, file);
addSuccessfullyUploadedFile(file);
iterator.remove();
}
// Broadcast completion only if the user has not cancelled the operation.
if (shouldContinue) {
broadcastCompleted(new ServerResponse(UploadTask.TASK_COMPLETED_SUCCESSFULLY,
UploadTask.EMPTY_RESPONSE, null));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
Logger.debug(LOG_TAG, "Logout and disconnect from FTP server: "
+ params.serverUrl + ":" + ftpParams.port);
ftpClient.logout();
ftpClient.disconnect();
} catch (Exception exc) {
Logger.error(LOG_TAG, "Error while closing FTP connection to: "
+ params.serverUrl + ":" + ftpParams.port, exc);
}
}
ftpClient = null;
}
}
我要评论