兼容某些ftp服务器,自动修复url中的//

pull/330/head
AriaLyy 7 years ago
parent 88dfa7eedc
commit 516fe9e598
  1. 4
      Aria/build.gradle
  2. 2
      Aria/src/main/java/com/arialyy/aria/core/common/AbsFtpInfoThread.java
  3. 10
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  4. 11
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java
  5. 6
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
  6. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsUploadTarget.java
  7. 16
      Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java
  8. 31
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
  9. 19
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  10. 3
      DEV_LOG.md
  11. 2
      README.md
  12. 9
      app/src/main/java/com/arialyy/simple/download/FtpDownloadActivity.java
  13. 2
      app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
  14. 6
      app/src/main/java/com/arialyy/simple/upload/FtpUploadActivity.java

@ -22,8 +22,8 @@ dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile project(':AriaAnnotations')
// compile 'com.arialyy.aria:aria-ftp-plug:1.0.3'
// compile project(':AriaAnnotations')
compile 'com.arialyy.aria:aria-ftp-plug:1.0.3'
compile project(':AriaFtpPlug')
}

@ -79,7 +79,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
new String(setRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
FTPFile[] files = client.listFiles(remotePath);
String s = client.getReplyString();
ALog.w(TAG, s);
ALog.i(TAG, s);
boolean isExist = files.length != 0;
if (!isExist && !isUpload) {
failDownload("文件不存在,任务链接【" + mTaskEntity.urlEntity.url + "】", false);

@ -108,7 +108,7 @@ public class DownloadReceiver extends AbsReceiver {
* </pre>
*/
@Deprecated public DownloadTarget load(@NonNull String url, boolean refreshInfo) {
CheckUtil.checkUrl(url);
url = CheckUtil.checkUrl(url);
return new DownloadTarget(url, targetName, refreshInfo);
}
@ -165,7 +165,7 @@ public class DownloadReceiver extends AbsReceiver {
* @param refreshInfo 是否刷新下载信息
*/
public FtpDownloadTarget loadFtp(@NonNull String url, boolean refreshInfo) {
CheckUtil.checkUrl(url);
url = CheckUtil.checkUrl(url);
return new FtpDownloadTarget(url, targetName, refreshInfo);
}
@ -183,7 +183,7 @@ public class DownloadReceiver extends AbsReceiver {
* 加载ftp文件夹下载地址
*/
public FtpDirDownloadTarget loadFtpDir(@NonNull String dirUrl) {
CheckUtil.checkUrl(dirUrl);
dirUrl = CheckUtil.checkUrl(dirUrl);
return new FtpDirDownloadTarget(dirUrl, targetName);
}
@ -239,7 +239,7 @@ public class DownloadReceiver extends AbsReceiver {
* 通过下载链接获取下载实体
*/
public DownloadEntity getDownloadEntity(String downloadUrl) {
CheckUtil.checkUrl(downloadUrl);
downloadUrl = CheckUtil.checkUrl(downloadUrl);
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl);
}
@ -247,7 +247,7 @@ public class DownloadReceiver extends AbsReceiver {
* 通过下载链接获取保存在数据库的下载任务实体
*/
public DownloadTaskEntity getDownloadTask(String downloadUrl) {
CheckUtil.checkUrl(downloadUrl);
downloadUrl = CheckUtil.checkUrl(downloadUrl);
DownloadEntity entity = getDownloadEntity(downloadUrl);
if (entity == null || TextUtils.isEmpty(entity.getDownloadPath())) return null;
return DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false'",

@ -34,7 +34,7 @@ import org.apache.commons.net.ftp.FTPReply;
* Ftp下载任务
*/
class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity> {
private final String TAG = "FtpThreadTask";
private final String TAG = "FtpDownloadThreadTask";
FtpThreadTask(StateConstance constance, IDownloadListener listener,
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
@ -64,22 +64,21 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
}
//发送第二次指令时,还需要再做一次判断
int reply = client.getReplyCode();
if (reply == FTPReply.SYNTAX_ERROR_IN_ARGUMENTS) {
ALog.e(TAG, "FTP没有打开写权限,断点续传失败,将从0开始读文件");
} else if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
client.disconnect();
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
fail(mChildCurrentLocation, "获取文件信息错误,错误码为:" + reply + ",msg:" + client.getReplyString(),
null);
client.disconnect();
return;
}
String remotePath =
new String(mTaskEntity.urlEntity.remotePath.getBytes(charSet), SERVER_CHARSET);
ALog.i(TAG, "remotePath【" + remotePath + "】");
is = client.retrieveFileStream(remotePath);
reply = client.getReplyCode();
if (!FTPReply.isPositivePreliminary(reply)) {
client.disconnect();
fail(mChildCurrentLocation, "获取流失败,错误码为:" + reply + ",msg:" + client.getReplyString(),
null);
client.disconnect();
return;
}

@ -16,12 +16,12 @@
package com.arialyy.aria.core.download.downloader;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.io.IOException;
import java.net.HttpURLConnection;
@ -130,12 +130,14 @@ class HttpFileInfoThread implements Runnable {
private void handle302Turn(HttpURLConnection conn) throws IOException {
String newUrl = conn.getHeaderField(mTaskEntity.redirectUrlKey);
ALog.d(TAG, "30x跳转,location【 " + mTaskEntity.redirectUrlKey + "】" + "新url为【" + newUrl + "】");
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null") || !newUrl.startsWith(
"http")) {
if (onFileInfoListener != null) {
onFileInfoListener.onFail(mEntity.getUrl(), "获取重定向链接失败", false);
}
return;
}
newUrl = CheckUtil.checkUrl(newUrl);
String cookies = conn.getHeaderField("Set-Cookie");
conn = (HttpURLConnection) new URL(newUrl).openConnection();
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);

@ -35,7 +35,7 @@ public abstract class AbsUploadTarget<TARGET extends AbsUploadTarget, ENTITY ext
* @param uploadUrl 上传路径
*/
public TARGET setUploadUrl(@NonNull String uploadUrl) {
CheckUtil.checkUrl(uploadUrl);
uploadUrl = CheckUtil.checkUrl(uploadUrl);
if (mEntity.getUrl().equals(uploadUrl)) return (TARGET) this;
mEntity.setUrl(uploadUrl);
mEntity.update();

@ -53,12 +53,15 @@ public class FtpUploadTarget
}
/**
* 设置上传路径
* 设置上传路径FTP上传路径必须是从"/"开始的完整路径
*
* @param uploadUrl 上传路径
*/
public FtpUploadTarget setUploadUrl(@NonNull String uploadUrl) {
CheckUtil.checkUrl(uploadUrl);
uploadUrl = CheckUtil.checkUrl(uploadUrl);
if (!uploadUrl.endsWith("/")) {
uploadUrl += "/";
}
mTaskEntity.urlEntity = CommonUtil.getFtpUrlInfo(uploadUrl);
if (mEntity.getUrl().equals(uploadUrl)) return this;
mEntity.setUrl(uploadUrl);
@ -66,6 +69,15 @@ public class FtpUploadTarget
return this;
}
/**
* 设置字符编码
*/
public FtpUploadTarget charSet(String charSet) {
if (TextUtils.isEmpty(charSet)) return this;
mTaskEntity.charSet = charSet;
return this;
}
/**
* ftp 用户登录信
* 设置登录信息需要在设置上传链接之后{@link #setUploadUrl(String)}

@ -35,7 +35,7 @@ import org.apache.commons.net.ftp.OnFtpInputStreamListener;
* FTP 单线程上传任务需要FTP 服务器给用户打开删除和读入IO的权限
*/
class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
private final String TAG = "FtpThreadTask";
private final String TAG = "FtpUploadThreadTask";
private String dir, remotePath;
FtpThreadTask(StateConstance constance, IEventListener listener,
@ -61,25 +61,13 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
client = createClient();
if (client == null) return;
initPath();
if (client.makeDirectory(dir)) {
fail(mChildCurrentLocation, "创建文件夹失败", null);
return;
}
if (client.changeWorkingDirectory(dir)) {
fail(mChildCurrentLocation, "选择工作文件夹失败", null);
return;
}
client.makeDirectory(dir);
client.changeWorkingDirectory(dir);
client.setRestartOffset(mConfig.START_LOCATION);
int reply = client.getReplyCode();
if (reply == FTPReply.SYNTAX_ERROR_IN_ARGUMENTS) {
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) {
fail(mChildCurrentLocation, "上传失败,错误码为:" + reply + ",msg:" + client.getReplyString(), null);
client.disconnect();
fail(mChildCurrentLocation,
"上传失败,FTP没有打开写权限,错误码为:" + reply + ",msg:" + client.getReplyString(), null);
return;
} else if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
client.disconnect();
fail(mChildCurrentLocation,
"上传失败,FTP没有打开写权限,错误码为:" + reply + ",msg:" + client.getReplyString(), null);
return;
}
@ -126,7 +114,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
private void initPath() throws UnsupportedEncodingException {
dir = new String(mTaskEntity.urlEntity.remotePath.getBytes(charSet), SERVER_CHARSET);
remotePath = new String(
(mTaskEntity.urlEntity.remotePath + "/" + mEntity.getFileName()).getBytes(charSet),
("/" + mTaskEntity.urlEntity.remotePath + mEntity.getFileName()).getBytes(charSet),
SERVER_CHARSET);
}
@ -134,6 +122,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
throws IOException {
try {
ALog.d(TAG, "remotePath【" + remotePath + "】");
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
boolean isStoped = false;
@ -160,11 +149,13 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
if (reply != FTPReply.TRANSFER_ABORTED) {
fail(mChildCurrentLocation, "上传文件错误,错误码为:" + reply + ",msg:" + client.getReplyString(),
null);
}
if (client.isConnected()) {
client.disconnect();
}
if (reply == FTPReply.TRANSFER_ABORTED) return;
fail(mChildCurrentLocation, "上传文件错误,错误码为:" + reply, null);
}
}

@ -74,7 +74,7 @@ public class CheckUtil {
* 检查下载实体
*/
public static void checkDownloadEntity(DownloadEntity entity) {
checkUrl(entity.getUrl());
entity.setUrl(checkUrl(entity.getUrl()));
checkPath(entity.getDownloadPath());
}
@ -88,14 +88,25 @@ public class CheckUtil {
}
/**
* 检测下载链接是否为null
* 检测下载链接是否合法如果地址中path是"//"而不是"/"将会改为"/"
*/
public static void checkUrl(String url) {
public static String checkUrl(String url) {
if (TextUtils.isEmpty(url)) {
throw new IllegalArgumentException("下载链接不能为null");
throw new IllegalArgumentException("url不能为null");
} else if (!url.startsWith("http") && !url.startsWith("ftp")) {
throw new IllegalArgumentException("url错误");
}
int index = url.indexOf("://");
if (index == -1) {
throw new IllegalArgumentException("url不合法");
}
String temp = url.substring(index + 3, url.length());
if (temp.contains("//")) {
temp = url.substring(0, index + 3) + temp.replaceAll("//", "/");
ALog.w(TAG, "url中含有//,//将转换为/,转换后的url为:" + temp);
return temp;
}
return url;
}
/**

@ -1,4 +1,7 @@
## 开发日志
+ v_3.3.14
- 修复ftp上传和下载的兼容性问题
- 如果url中的path有"//"将替换为"/"
+ v_3.3.13
- 添加`@Download.onWait、@Upload.onWait、@DownloadGroup.onWait`三个新注解,队列已经满了,继续创建新任务,任务处于等待中,将会执行被这三个注解标志的方法
- app被kill,但是还存在等待中的任务A;第二次重新启动,先创建一个新的任务B,Aria会自动把B放进等待队列中,这时再次创建任务A,会导致重复下载,进度错乱的问题;本版本已修复这个问题

@ -33,7 +33,7 @@ annotationProcessor 'com.arialyy.aria:aria-compiler:3.3.13'
```
如果出现android support,请将 `compile 'com.arialyy.aria:aria-core:3.3.13'`替换为
```
compile('com.arialyy.aria:<last-version>'){
compile('com.arialyy.aria:aria-core:<last-version>'){
exclude group: 'com.android.support'
}
```

@ -39,8 +39,10 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
//private final String URL = "ftp://192.168.1.9:21/下载/[电影天堂www.dy2018.com]赛车总动员3BD中英双字.mp4";
//private final String URL = "ftp://h:h@tv.dl1234.com:2199/付岩洞复仇者们05.mkv";
//private final String URL = "ftp://z:z@dygod18.com:21211/[破晓电影www.poxiao.com]情遇曼哈顿HD国语中字.mkv";
private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg";
//private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg";
//private final String URL = "ftp://192.168.1.6:21/download/AriaPrj.zip";
//private final String URL = "ftp://172.18.104.71:21/upload/AS.zip";
private final String URL = "ftp://d:d@dygodj8.com:12311/[电影天堂www.dy2018.com]脑火BD中字.mp4";
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
@ -61,8 +63,9 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
Aria.download(this).loadFtp(URL, true).charSet("utf-8")
.login("sxf", "B34VdGsJ")
Aria.download(this).loadFtp(URL, true).charSet("gbk")
//.login("sxf", "B34VdGsJ")
//.login("lao", "123456")
.setDownloadPath("/mnt/sdcard/").start();
break;
case R.id.stop:

@ -238,6 +238,6 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
@Override protected void onDestroy() {
super.onDestroy();
Aria.download(this).unRegister();
//Aria.download(this).unRegister();
}
}

@ -34,8 +34,8 @@ import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
* Ftp 文件上传demo
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
private final String FILE_PATH = "/mnt/sdcard/gg.zip";
private final String URL = "ftp://192.168.1.2:21/upload/测试";
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.zip";
private final String URL = "ftp://192.168.1.6:21/aa/你好";
@Override protected void init(Bundle savedInstanceState) {
setTile("D_FTP 文件上传");
@ -56,7 +56,7 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").add();
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start();
break;
case R.id.stop:
Aria.upload(this).loadFtp(FILE_PATH).stop();

Loading…
Cancel
Save