Skip to content

Commit

Permalink
1. 支持data uri 协议数据下载
Browse files Browse the repository at this point in the history
  • Loading branch information
Justson committed Dec 15, 2021
1 parent e65a9ee commit d5e12ca
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 41 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ dependencies {
implementation "com.android.support:design:${SUPPORT_LIB_VERSION}"
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
// implementation project(':library')
implementation 'com.github.Justson:Downloader:v4.2.0'
implementation project(':library')
// implementation 'com.github.Justson:Downloader:v4.2.0'
implementation 'com.github.Justson.AgentWeb:agentweb:v4.1.8'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.liulishuo.filedownloader:library:1.7.4'
Expand Down
17 changes: 13 additions & 4 deletions app/src/main/java/com/download/sample/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,19 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
this.findViewById(R.id.resumeAllBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (DownloadImpl.getInstance(getApplicationContext()).pausedTasksTotals() > 0) {
DownloadImpl.getInstance(getApplicationContext()).resumeAll();
// downloadAdapter.notifyDataSetChanged();
}
// if (DownloadImpl.getInstance(getApplicationContext()).pausedTasksTotals() > 0) {
// DownloadImpl.getInstance(getApplicationContext()).resumeAll();
//// downloadAdapter.notifyDataSetChanged();
// }
DownloadImpl.getInstance(MainActivity.this).url("data:application/vnd.ms-excel;base64,PGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6b2ZmaWNlIiAKICB4bWxuczp4PSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOm9mZmljZTpleGNlbCIgCiAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1JFQy1odG1sNDAiPgogIDxoZWFkPjxtZXRhIGNoYXJzZXQ9IlVURi04Ij48IS0tW2lmIGd0ZSBtc28gOV0+PHhtbD48eDpFeGNlbFdvcmtib29rPjx4OkV4Y2VsV29ya3NoZWV0cz48eDpFeGNlbFdvcmtzaGVldD4KICAgIDx4Ok5hbWU+MjAyMeW5tDEy5pyIMTXml6XlupPlrZjpooTorablr7zlh7rmlbDmja48L3g6TmFtZT4KICAgIDx4OldvcmtzaGVldE9wdGlvbnM+PHg6RGlzcGxheUdyaWRsaW5lcy8+PC94OldvcmtzaGVldE9wdGlvbnM+PC94OkV4Y2VsV29ya3NoZWV0PgogICAgPC94OkV4Y2VsV29ya3NoZWV0cz48L3g6RXhjZWxXb3JrYm9vaz48L3htbD48IVtlbmRpZl0tLT4KICAgIDwvaGVhZD48Ym9keT48dGFibGU+PHRyPjx0ZD7lkI3np7AJPC90ZD48dGQ+5bqT5a2YCTwvdGQ+PHRkPuWNleS9jQk8L3RkPjx0ZD7liIbnsbsJPC90ZD48dGQ+5bqT5a2Y5LiK6ZmQCTwvdGQ+PHRkPuW6k+WtmOS4i+mZkAk8L3RkPjx0ZD7kvpvlupTllYYJPC90ZD48dGQ+6aKE6K2m57G75Z6LCTwvdGQ+PHRkPumihOitpuWAvAk8L3RkPjwvdHI+PHRyPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+6L6J54WM5o2u5LqG6KejCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4wLjAwCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij43OTQ2CTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij7mtYvor5UxCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4xMDAwMC4wMDAJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPjIuMDAwCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4JPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPuW6k+WtmOS4jei2swk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+LTIuMDAwCTwvdGQ+PC90cj48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPua1i+ivlTEJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPi0xLjAwCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij7ljIUJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPua1i+ivlQk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+MjAuMDAwCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij41LjAwMAk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+CTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij7lupPlrZjkuI3otrMJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPi02LjAwMAk8L3RkPjwvdHI+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij42NWfniZvmtarmsYnniZvogonlubLvvIjpppnovqPvvIkJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPjAuMDAJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPuiiiwk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+5LyR6Zey6aOf5ZOBCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4wLjAwMAk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+Mi4wMDAJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPuiHquiQpQk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+5bqT5a2Y5LiN6LazCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4tMi4wMDAJPC90ZD48L3RyPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+NTBn5Y+v5q+U5YWL57qv5YiH55Wq6IyE5ZGzCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij43MC4wMAk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+5YyFCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij7mlaPnp7Dpo5/lk4EJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPjUwLjAwMAk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+MC4wMDAJPC90ZD48dGQgc3R5bGU9Im1zby1udW1iZXItZm9ybWF0OidAJzsiPuiHquiQpQk8L3RkPjx0ZCBzdHlsZT0ibXNvLW51bWJlci1mb3JtYXQ6J0AnOyI+5bqT5a2Y6L+H5YmpCTwvdGQ+PHRkIHN0eWxlPSJtc28tbnVtYmVyLWZvcm1hdDonQCc7Ij4yMC4wMDAJPC90ZD48L3RyPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4=")
.autoOpenIgnoreMD5()
.setEnableIndicator(true)
.enqueue(new DownloadListenerAdapter(){
@Override
public boolean onResult(Throwable throwable, Uri path, String url, Extra extra) {
return super.onResult(throwable, path, url, extra);
}
});
}
});
this.findViewById(R.id.cancelAllBtn).setOnClickListener(new View.OnClickListener() {
Expand Down
6 changes: 6 additions & 0 deletions library/src/main/java/com/download/library/DownloadTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Base64;

import com.queue.library.GlobalQueue;

Expand Down Expand Up @@ -511,6 +512,11 @@ protected void createNotifier() {
}
}

boolean isDataURI() {
return !TextUtils.isEmpty(mUrl) && mUrl.startsWith("data");
}


String getRedirect() {
return redirect;
}
Expand Down
66 changes: 66 additions & 0 deletions library/src/main/java/com/download/library/Downloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import android.os.StatFs;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;

import java.io.BufferedInputStream;
Expand Down Expand Up @@ -230,6 +231,12 @@ protected Integer doInBackground() {
if (downloadTask.isCanceled()) {
return ERROR_USER_CANCEL;
}

if (downloadTask.isDataURI()) {
error = transferDataFromUrl();
return error;
}

this.mBeginTime = SystemClock.elapsedRealtime();
if (!checkNet()) {
Runtime.getInstance().logError(TAG, " Network error,isForceDownload:" + mDownloadTask.isForceDownload());
Expand Down Expand Up @@ -311,6 +318,65 @@ protected Integer doInBackground() {
return error;
}

private int transferDataFromUrl() {
DownloadTask downloadTask = mDownloadTask;
String url = downloadTask.getUrl();
if (!url.startsWith("data")) {
return ERROR_LOAD;
}
if (!url.contains(",")) {
return ERROR_LOAD;
}
String base64EncodedString = extractContent();
if (TextUtils.isEmpty(base64EncodedString)) {
return ERROR_LOAD;
}
byte[] decodedBytes = Base64.decode(base64EncodedString, Base64.DEFAULT);
downloadTask.setContentLength(decodedBytes.length);
downloadTask.setTotalsLength(decodedBytes.length);
RandomAccessFile out = null;
try {
out = new LoadingRandomAccessFile(downloadTask.getFile());
out.seek(0L);
out.write(decodedBytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
progressFinaly();
closeIO(out);
}
return SUCCESSFUL;
}


String extractContent() {
DownloadTask downloadTask = mDownloadTask;
if (!downloadTask.isDataURI()) {
return "";
}
String url = downloadTask.mUrl;
int end;
if ((end = url.indexOf(",", 5)) <= 5) {
return "";
}
int start = -1;
for (int i = end; i >= 5; i--) {
String alpha = String.valueOf(url.charAt(i));
if (alpha.equals(";") || alpha.equals(":")) {
start = i + 1;
break;
}
}

String chartset = url.substring(start, end);
if (!chartset.equalsIgnoreCase("base64")) {
Runtime.getInstance().log(TAG, "unsupport chartset:" + chartset);
return "";
}
String base64EncodedString = url.substring(url.indexOf(",", 5) + 1);
return base64EncodedString;
}

private int doDownload() throws IOException {
DownloadTask downloadTask = this.mDownloadTask;
downloadTask.updateTime(this.mBeginTime);
Expand Down
1 change: 0 additions & 1 deletion library/src/main/java/com/download/library/Extra.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ public boolean isCalculateMD5() {
}



protected Extra copy(Extra copy) {
copy.mIsForceDownload = this.mIsForceDownload;
copy.mEnableIndicator = this.mEnableIndicator;
Expand Down
86 changes: 52 additions & 34 deletions library/src/main/java/com/download/library/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.BufferedReader;
import java.io.File;
Expand Down Expand Up @@ -63,6 +64,7 @@ public final class Runtime {
private static final Pattern CONTENT_DISPOSITION_WITHOUT_ASTERISK_PATTERN =
Pattern.compile("attachment;\\s*filename\\s*=\\s*\"*([^\"\\n]*)\"*");
static final String PREFIX = "Download-";
private static final String TAG = Runtime.class.getSimpleName();
boolean DEBUG = BuildConfig.DEBUG;
private String authority;
private StorageEngine mStorageEngine;
Expand Down Expand Up @@ -170,16 +172,17 @@ public int generateGlobalThreadId() {
return mThreadGlobalCounter.getAndIncrement();
}

public File createFile(Context context, Extra extra) {
return createFile(context, extra, null);
public File createFile(Context context, DownloadTask downloadTask) {
return createFile(context, downloadTask, null);
}

public File createFile(Context context, Extra extra, File dir) {
public File createFile(Context context, DownloadTask downloadTask, File dir) {
String fileName = "";
try {
fileName = getFileNameByContentDisposition(extra.getContentDisposition());
if (TextUtils.isEmpty(fileName) && !TextUtils.isEmpty(extra.getUrl())) {
Uri mUri = Uri.parse(extra.getUrl());

fileName = getFileNameByContentDisposition(downloadTask.getContentDisposition());
if (TextUtils.isEmpty(fileName) && !TextUtils.isEmpty(downloadTask.getUrl())) {
Uri mUri = Uri.parse(downloadTask.getUrl());
if (null != mUri && !TextUtils.isEmpty(mUri.getPath()) && mUri.getPath().contains("/")) {
fileName = mUri.getPath().substring(mUri.getPath().lastIndexOf('/') + 1);
}
Expand All @@ -188,23 +191,48 @@ public File createFile(Context context, Extra extra, File dir) {
fileName = fileName.substring(fileName.length() - 64, fileName.length());
}
if (TextUtils.isEmpty(fileName)) {
fileName = md5(extra.getUrl());
fileName = md5(downloadTask.getUrl());
}
if (fileName.contains("\"")) {
fileName = fileName.replace("\"", "");
}
String path = (dir == null || !dir.isDirectory()) ? getDir(context, extra.isEnableIndicator() || extra.isAutoOpen()).getPath() : dir.getAbsolutePath();
String path = (dir == null || !dir.isDirectory()) ? getDir(context, downloadTask.isEnableIndicator() || downloadTask.isAutoOpen()).getPath() : dir.getAbsolutePath();
File pathFile = new File(path);
if (!pathFile.exists()) {
pathFile.mkdirs();
}
return createFileByName(pathFile, context, fileName, !extra.isBreakPointDownload());
if (downloadTask.isDataURI() && !fileName.contains(".")) {
String extension = findExtensionFromUri(downloadTask.getUrl());
// log(TAG, "extension:" + extension);
fileName = fileName + "." + extension;
// fileName = fileName + extension;

}
return createFileByName(pathFile, context, fileName, !downloadTask.isBreakPointDownload());
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}

private String findExtensionFromUri(String url) {
int end = -1;
for (int i = 5; i < url.length(); i++) {
String c = String.valueOf(url.charAt(i));
if (c.equalsIgnoreCase(";")) {
end = i;
} else if (c.equalsIgnoreCase(",")) {
break;
}
}
if (end > 5) {
String mimeType = url.substring(5, end);
log(TAG, "mimeType:" + mimeType);
return MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
}
return "";
}

boolean checkWifi(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
Expand Down Expand Up @@ -283,7 +311,9 @@ public File getDefaultDir(Context context) {

public void log(String tag, String msg) {
if (DEBUG) {
Log.i(tag, msg);
if (!TextUtils.isEmpty(msg)) {
Log.i(tag, msg);
}
}
}

Expand Down Expand Up @@ -373,7 +403,7 @@ public String getApplicationName(Context context) {

public Intent getCommonFileIntentCompat(Context context, DownloadTask downloadTask) {
Intent mIntent = new Intent().setAction(Intent.ACTION_VIEW);
setIntentDataAndType(context, mIntent, getMIMEType(downloadTask.getFile()), downloadTask.getFile(), false, downloadTask.isCustomFile() ? downloadTask.getAuthority() : getAuthority(downloadTask.getContext()));
setIntentDataAndType(context, mIntent, getMimeType(downloadTask.getFile()), downloadTask.getFile(), false, downloadTask.isCustomFile() ? downloadTask.getAuthority() : getAuthority(downloadTask.getContext()));
return mIntent;
}

Expand Down Expand Up @@ -413,29 +443,17 @@ public void setIntentDataAndType(Context context,
}
}

public String getMIMEType(File f) {
String type = "";
String fName = f.getName();
String end = fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase();
if (end.equals("pdf")) {
type = "application/pdf";
} else if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") ||
end.equals("xmf") || end.equals("ogg") || end.equals("wav")) {
type = "audio/*";
} else if (end.equals("3gp") || end.equals("mp4")) {
type = "video/*";
} else if (end.equals("jpg") || end.equals("gif") || end.equals("png") ||
end.equals("jpeg") || end.equals("bmp")) {
type = "image/*";
} else if (end.equals("apk")) {
type = "application/vnd.android.package-archive";
} else if (end.equals("pptx") || end.equals("ppt")) {
type = "application/vnd.ms-powerpoint";
} else if (end.equals("docx") || end.equals("doc")) {
type = "application/vnd.ms-word";
} else if (end.equals("xlsx") || end.equals("xls")) {
type = "application/vnd.ms-excel";
} else {
public String getMimeType(File file) {
String type;
String fileName = file.getName();
if (!fileName.contains(".")) {
type = "*/*";
return type;
}
String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
Runtime.getInstance().log(TAG, type);
if (TextUtils.isEmpty(type)) {
type = "*/*";
}
return type;
Expand Down

0 comments on commit d5e12ca

Please sign in to comment.