본문 바로가기
Android

안드로이드(Android) 하이브리드(Hybrid)앱 첨부파일 다운로드

by 일용직 코딩노동자 2020. 2. 26.
728x90
반응형

Webview 하시면서 웹개발자가 게시판같은곳에 첨부파일을 올려놓습니다.

 

이걸 다운받을려면 따로 설정을 해줘야하는데요.

 

그걸 한번 포스팅 해보겠습니다.

 

  mWebView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                try {
                    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
                    DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

                    contentDisposition = URLDecoder.decode(contentDisposition,"UTF-8"); //디코딩
                    String FileName = contentDisposition.replace("attachment; filename=", ""); //attachment; filename*=UTF-8''뒤에 파일명이있는데 파일명만 추출하기위해 앞에 attachment; filename*=UTF-8''제거

					String cookie = CookieManager.getInstance().getCookie(url);
                    request.addRequestHeader("Cookie", cookie);
                    
                    String fileName = FileName; //위에서 디코딩하고 앞에 내용을 자른 최종 파일명
                    request.setMimeType(mimetype);
                    request.addRequestHeader("User-Agent", userAgent);
                    request.setDescription("Downloading File");
                    request.setAllowedOverMetered(true);
                    request.setAllowedOverRoaming(true);
                    request.setTitle(fileName);
                    request.setRequiresCharging(false);

                    request.allowScanningByMediaScanner();
                    request.setAllowedOverMetered(true);
                    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
                    dm.enqueue(request);
                    Toast.makeText(getApplicationContext(),"파일이 다운로드됩니다.", Toast.LENGTH_LONG).show();
                }
                catch (Exception e) {
                    if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                            Toast.makeText(getBaseContext(), "다운로드를 위해\n권한이 필요합니다.", Toast.LENGTH_LONG).show();
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1004);
                        }
                        else {
                            Toast.makeText(getBaseContext(), "다운로드를 위해\n권한이 필요합니다.", Toast.LENGTH_LONG).show();
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1004);
                        }
                    }
                }
            }
        });

전체코드입니다.

 

onCreate안에 넣어주시면 되는데요.

 

첨부파일을 누르는 순간 리스너가 호출되고, 오버라이드메소드에서 다운로드 url을 받고

 

userAgent에서는 기기의 정보 및 브라우저 정보들이 담겨있습니다.

 

그리고 중요한 2가지가 있는데, contentDisposition이녀석은 결정적으로 파일이름 입니다.

 

소스코드 보시면

 

contentDisposition = URLDecoder.decode(contentDisposition,"UTF-8");

 

이부분이 있는데요 파일이름이 한글로 되어있는경우 한글이 깨지는 현상이 발생합니다.

 

그래서 디코딩을 통해 한글로 정상출력 가능하게 해준다음,

 

String FileName = contentDisposition.replace("attachment; filename=", "");

 

이코드를 보시면 파일이름.확장자 앞에 attachment; filename= 이런문구가 붙어있습니다.

 

이 문구는 다 달라요 저렇게 안나오실수도있습니다.

 

그럴땐 로그로 contentDisposition값을 찍어서 보신다음 앞에 뭐라고 나오는지 보신 후,

 

위 코드처럼 replace를 통해서 앞에 불필요한 부분을 없애줍니다.

 

replace는 앞에 인자값에 들어간 String형 문자열을 두번째 인자값으로 바꾸겠다는건데 저는 ""로 되어있기때문에

지워 집니다.

 

그럼 순수 파일명.확장자 만 남게되는데요 그게 이제 진짜 파일이름 입니다.

 

이제 그다음에 mimetype가 있는데 이녀석은 확장자를 안드로이드(WebView)에게 알려줍니다.

 

아 지금 이파일 확장자가 뭐 hwp야! pdf야! 라고 알려줍니다.

 

그뒤에 코드들은 이제 다운로드에 필요한녀석들을 셋팅해줍니다.

 

파일이름은 무엇이고 이 브라우저 정보가 어떻게되고 확장자타입은 어떤것이며 저장은 어디에 할것인지 등등 지정해줍니다.

 

request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);

이녀석이 앞에 인자가 저장경로 뒤에 인자가 어떤이름으로 저장할것인지

 

fileName는 아까 저희가 replace로 만들었죠? 그대로 적어주시면됩니다.

 

밑에 이제 catch문이 있습니다.

 

다운로드를 위해서는 권한이 필요한데,

 

WRITE_EXTERNAL_STORAGE 권한이 필요한데요.

 

우선 메니페스트에서

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

저는 그냥 둘다 넣어줬습니다.

 

저장소 권한은 위험권한 이기때문에 퍼미션체크를 해주셔야합니다.

 

박상권님 블로그에 implementation 'gun0912.ted:tedpermission:2.0.0' 라는 라이브러리를 해놓으셨는데

 

매우 유용한 라이브러리 입니다. 퍼미션을 복잡하게 하지않고 바로바로 체크할수있습니다.

 

이렇게 셋팅해주시면 첨부파일 다운로드가 완료됩니다.

 

한글문서나 pdf문서같은 경우 뷰어가 따로 설치되어야 열릴수있습니다.

 

도움이 되셨다면 하트와 궁금하신 사항은 댓글을 남겨주세요.

728x90
반응형

댓글