How to get downloaded file name from DownloadManager

拥有回忆 提交于 2020-12-26 12:06:12

问题


I have two fragments in a tab view layout. I am working with WebView() and DownloadManager() to download a file. My file is downloading perfectly but the downloaded file doesn't have the original file name. This is my problem. How do I get the original file name? I found some code here for this issue, but none of them helped me...

Here is my fragment where I am using the download manager:

public class Download extends Fragment {
    View v;
    WebView webView2;
    SwipeRefreshLayout mySwipeRefreshLayout;
    DownloadManager downloadManager;

    public String currentUrl = "";
    String myLink = "";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        v = inflater.inflate(R.layout.download, container, false);
        mySwipeRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swiperefresh);
        webView2 = (WebView) v.findViewById(R.id.webView_download);

        int permissionCheck = ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.WRITE_EXTERNAL_STORAGE);

        webView2.setInitialScale(1);
        webView2.getSettings().setJavaScriptEnabled(true);
        webView2.getSettings().setLoadWithOverviewMode(true);
        webView2.getSettings().setUseWideViewPort(true);
        webView2.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        webView2.setScrollbarFadingEnabled(false);
        webView2.setVerticalScrollBarEnabled(false);
        webView2.loadUrl(currentUrl);
        webView2.setWebViewClient(new WebViewClient());
        webView2.getSettings().setBuiltInZoomControls(true);
        webView2.getSettings().setUseWideViewPort(true);
        webView2.getSettings().setLoadWithOverviewMode(true);
        webView2.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        webView2.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return (event.getAction() == MotionEvent.ACTION_MOVE);
            }
        });

        if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
            Bundle bundle = getArguments();

            if (bundle != null) {
                String value = getArguments().getString("link");
                myLink = value;
                webView2.loadUrl(myLink);
            }

            webView2.setDownloadListener(new DownloadListener() {
                public void onDownloadStart(String url, String userAgent,
                                            String contentDisposition, String mimetype,
                                            long contentLength) {
                    Intent i = new Intent(Intent.ACTION_VIEW);
                    i.setData(Uri.parse(url));

                    downloadManager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
                    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
                    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "Youtube_Video" + ".mp4");
                    request.allowScanningByMediaScanner();
                    Long reference = downloadManager.enqueue(request);

                    Toast.makeText(getContext(), "Downloading...", Toast.LENGTH_LONG).show();
                }
            });
        } else {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }

        return v;
    }
}

回答1:


You are ignoring the contentDisposition parameter which you are receiving in your onDownloadStart() method — when the file is downloaded for example via a form submit or a POST request or sometimes via a GET method with redirect the Content-disposition header will usually contain the file name that you are looking for.

import android.webkit.URLUtil;

// ...

webView.setDownloadListener(new DownloadListener() {
    public void onDownloadStart(
        String url,
        String userAgent,
        String contentDisposition, // <<< HERE IS THE ANSWER <<<
        String mimetype,
        long contentLength) {

        String humanReadableFileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
        //     ^^^^^^^^^^^^^^^^^^^^^ the name you expect
    // ....


    });

Even though the contentDisposition will contain your original file name you will still need to use a BroadcastReceiver to get the actual content Uri:

    BroadcastReceiver onCompleteHandler = new BroadcastReceiver() {
        public void onReceive(Context ctx, Intent intent) {
            long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
            if (downloadId == downloadRef) {
                Log.d(TAG, "onReceive: " + intent);
                DownloadManager.Query query = new DownloadManager.Query();
                query.setFilterById(downloadId);
                Cursor cur = downloadManager.query(query);

                if (cur.moveToFirst()) {
                    int columnIndex = cur.getColumnIndex(DownloadManager.COLUMN_STATUS);
                    if (DownloadManager.STATUS_SUCCESSFUL == cur.getInt(columnIndex)) {
                        String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));

                        Uri uriDownloadedFile = Uri.parse(uriString);
                        // TODO: consume the uri
                }

            }
        }
    };
    registerReceiver(onCompleteHandler, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));



回答2:


HTTP doesn't include a separate filename generally. You can use the filename in the URL path, for example take everything after the last forward slash:

String filename = currentUrl.substring(currentUrl.lastIndexOf('/') + 1);

and then pass it into:

request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);

If there is a filename is in the headers however, a separate HEAD request would do the trick (see this answer).



来源:https://stackoverflow.com/questions/45086245/how-to-get-downloaded-file-name-from-downloadmanager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!