【问题标题】:How to get downloaded file name from DownloadManager如何从 DownloadManager 获取下载的文件名
【发布时间】:2020-12-01 20:52:57
【问题描述】:

我在选项卡视图布局中有两个片段。我正在使用 WebView() 和 DownloadManager() 下载文件。我的文件正在完美下载,但下载的文件没有原始文件名。这是我的问题。如何获取原始文件名?我在这里找到了一些解决这个问题的代码,但没有一个对我有帮助......

这是我使用下载管理器的片段:

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;
    }
}

【问题讨论】:

    标签: android android-fragments download-manager


    【解决方案1】:

    您忽略了您在onDownloadStart() 方法中接收到的contentDisposition 参数——当文件下载时,例如通过表单提交或POST 请求,或者有时通过带有重定向Content-disposition 标头的GET 方法通常会包含您要查找的文件名。

    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
        // ....
    
    
        });
    

    即使 contentDisposition 将包含您的原始文件名,您仍然需要使用 BroadcastReceiver 来获取实际内容 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 通常不包含单独的文件名。您可以在 URL 路径中使用文件名,例如取最后一个正斜杠之后的所有内容:

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

      然后传入:

      request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
      

      但是,如果标头中有文件名,则单独的 HEAD 请求可以解决问题(请参阅this answer)。

      【讨论】:

      • 它对我不起作用...下载的文件名如“watch?v=ZtgD9f0xPuU”现在是...但我现在可以使用名称
      • 如果您知道该信息的确切名称?
      • 那么在这种情况下文件名就是视频的标题?如果是这样,您需要在下载视频之前向 YouTube 请求标题(例如 here
      • 您似乎希望我们为您编写一些代码。虽然许多用户愿意为陷入困境的编码人员编写代码,但他们通常只有在发布者已经尝试自己解决问题时才会提供帮助。展示这项工作的一个好方法是包含您迄今为止编写的代码、示例输入(如果有的话)、预期输出以及您实际获得的输出(控制台输出、回溯等)。您提供的详细信息越多,您可能收到的答案就越多。
      猜你喜欢
      • 1970-01-01
      • 2012-10-30
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多