10

I'm using DownloadManager to download video files from a url.

The problem is if I use the default folder to download the file I can not see the video in the galery.

Also, If I try to use this method:

request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, 'filename');

I need to know the file name before download which in this case, I don't.

And also, I don't have the name of the file in the url.

How can I do to get the file name from the headers and pass the name to the method setDestinationInExternalPublicDir ? Other alternatives?

rodeleon
  • 362
  • 3
  • 18
  • 1
    "The problem is if I use the default folder to download the file I can not see the video in the galery" -- what did you do to make it show up in the Gallery? Did you use `MediaScannerConnnection` and `scanFile()`? Otherwise, it will not show up until the next periodic round of file indexing, which may be a while. "I need to know the file name before download which in this case, I don't" -- then issue an HTTP `HEAD` request or something so that you can get the filename. – CommonsWare Apr 14 '14 at 20:56
  • 3
    What it doesn't make sense to me is why DonwloadManager doesnt't provide a way to set just the destination folder and keep the name of the file from the server. I'm missing something here? Thanks for your time again. – rodeleon Apr 14 '14 at 22:28
  • That'd be a nice feature, but `DownloadManager` doesn't offer it. – CommonsWare Apr 14 '14 at 22:30
  • 6
    Getting file name from the download response header? I think this would be a basic feature of a "DownloadManager". It's just frustrating to work with Android at times. – Robert Kang May 14 '14 at 13:24

5 Answers5

10

In case anyone want an implementation of doing a HEAD request to get the filename:

class GetFileName extends AsyncTask<String, Integer, String>
{
    protected String doInBackground(String... urls)
    {
        URL url;
        String filename = null;
        try {
            url = new URL(urls[0]);
            String cookie = CookieManager.getInstance().getCookie(urls[0]);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestProperty("Cookie", cookie);
            con.setRequestMethod("HEAD");
            con.setInstanceFollowRedirects(false);
            con.connect();

            String content = con.getHeaderField("Content-Disposition");
            String contentSplit[] = content.split("filename=");
            filename = contentSplit[1].replace("filename=", "").replace("\"", "").trim();
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
        }
        return filename;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    @Override
    protected void onPostExecute(String result) {

    }
}
rodeleon
  • 362
  • 3
  • 18
  • Thanks! So there is no way to do it with the DownloadManager? :( I am downloading files from Google Drive and the only way to extract the file name is reading the headers – lasnow Mar 16 '19 at 00:44
4

Small tip, there is a nice helper method in Android

URLUtil.guessFileName(url, contentDisposition, contentType);

So after completing the call to the server, getting the contenttype and contentDisposition from the Headers this will try and find the filename from the information.

Raanan
  • 4,777
  • 27
  • 47
0

I got into the same problem.I used @rodeleon answer but there was no Content-Disposition in response header. Then I analyzed url header from Chrome dev tools and got 'Location' in response header which contained filename at the end, it was like "b/Ol/fire_mp3_24825.mp3". so instead of using

String content = con.getHeaderField("Content-Disposition")

I used

String content = con.getHeaderField("Location") 

and at the end in onPostExecute

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        String fileName = result.substring(result.lastIndexOf("/") + 1);
        // use result as file name
        Log.d("MainActivity", "onPostExecute: " + fileName);
    }
0

Method URLUtil.guessFileName() (while not yet knowing about the Content-Disposition) and also the meanwhile deprecated class AsyncTask are both kinda problematic approaches these days. To properly enqueue the download with the DownloadManager:

  • One first has to disable "following redirects" in whatever HTTP client (that's the clue).
  • Then the first response will be HTTP 302 (with a Location header), instead of HTTP 200.
  • When fetching that, one will get HTTP 200 with a Content-Disposition header (filename).
  • Only then one can enqueue with DownloadManager (whilst knowing the filename already).

Here's an example of mine: RepositoryFragment (a GitHub Client).

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
-4
    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, uri.getLastPathSegment());