🤖 안드로이드 Android

[안드로이드/Android] 웹뷰(WebView) 파일 다운로드

핑크빛연어 2021. 4. 5. 16:08

 

안드로이드에서 웹뷰(WebView) 구현 시 파일 다운로드 기능을 추가하는 작업을 구현해 보았습니다.

 

작성한 파일 목록 입니다.

 

 

1. AndroidManifest.xml

2. WebViewActivity.java

3. file.jsp (웹소스)

4. FileController.java (웹소스)

 

 

 

1. AndroidManifest.xml

 

저장소 파일 접근 권한 을 추가해야 합니다.

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

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

두개 다 추가해 주세요~

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.eun.myapp">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true" >

        <activity android:name=".WebViewActivity">
        	<intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

 

 

 

2. WebViewActivity.java

 

현재 소스에서는 파일다운로드 버튼을 클릭해도 아무런 반응이 일어나지 않습니다.

파일다운로드 버튼 클릭 시 파일 다운로드를 실행하기 위해서는 WebViewActivity 클래스 안에 다음과 같은 코드를 추가합니다.

 

onCreate() 에 웹뷰(webview) 를 설정해주는 부분에서 webView.setDownloadListener 를 추가해줍니다.

그러면 파일 다운로드를 누르는 순간 리스너가 호출됩니다.

 

WebViewClient 를 상속받고 DownloadListener 를 구현한 MyDownloadListener 클래스의 onDownloadStart() 메소드를 구현하여 파일 다운로드를 실행할 수 있습니다.

 

	@Override
    protected void onCreate(Bundle savedInstanceState) {
	    ...
		webView.setDownloadListener(new MyWebViewClient());    
   		...
    }
    
    
/* WebViewClient 를 상속받는 MyDownloadListener 클래스를 만들어 DownloadListener 를 구현해준다 */
    private class MyWebViewClient extends WebViewClient implements DownloadListener {

        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
            Log.d(TAG, "***** onDownloadStart()");

            Log.d(TAG,"***** onDownloadStart() - url : "+url);
            Log.d(TAG,"***** onDownloadStart() - userAgent : "+userAgent);
            Log.d(TAG,"***** onDownloadStart() - contentDisposition : "+contentDisposition);
            Log.d(TAG,"***** onDownloadStart() - mimeType : "+mimeType);

            //권한 체크
//          if(권한 여부) {
            //권한이 있으면 처리
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
            try {
                contentDisposition = URLDecoder.decode(contentDisposition, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            contentDisposition = contentDisposition.substring(0, contentDisposition.lastIndexOf(";"));
            request.setMimeType(mimeType);

            //------------------------COOKIE!!------------------------
            String cookies = CookieManager.getInstance().getCookie(url);
            request.addRequestHeader("cookie", cookies);
            //------------------------COOKIE!!------------------------
            request.addRequestHeader("User-Agent", userAgent);
            request.setDescription("Downloading file...");
            request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimeType));
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(url, contentDisposition, mimeType));
            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            dm.enqueue(request);
            Toast.makeText(getApplicationContext(), "파일을 다운로드합니다.", Toast.LENGTH_LONG).show();

//          } else {
            //권한이 없으면 처리
//          }
        }
    }

 

이렇게 해주면 파일다운로드 버튼 클릭 시 /내장메모리/Download/ 폴더 안에 다운로드 받은 파일이 저장됩니다.

 

 

 

3. file.jsp

 

웹뷰(WebView) 에 표시할 웹페이지에 파일 다운로드 버튼 클릭 시 첨부파일을 다운로드 하는 button 태그를 구현하고

/myweb/downloadFile.do 를 통해 첨부파일을 다운로드 하는 아주 아주 간단하게 테스트용 웹소스를 구현하였습니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>

<html>
<head>
	<title>Home</title>
	<script type="text/javascript" src="./resources/js/jquery-3.2.1.min.js"></script>
</head>

<body>
<h1 style="margin: 50px;">
	File
</h1>
<div style="margin-bottom: 50px;">
  <table style="width: 100%; height: 100px;">
    <tr>
	  <th style="font-size: xx-large; color: #8C8C8C; text-align: left; padding-left: 50px;">첨부파일 업로드/다운로드 </th>
    </tr>
  </table>
</div>

<div>
  <table style="width: 110%;background-color: #E4F7BA;">
    <tr>
      <td id="" style="padding: 25px 25px 10px 100px;">
        <form id="form_file" enctype="multipart/form-data">
          <div class="add_file" id="add_file_0">
            <input title="첨부파일 업로드" type="file" id="fileData_0" name="fileData_0" value="" style="font-size: xxx-large;">
          </div>
       </form>
      </td>
    </tr>
  </table>
</div>

<div>
  <table style="width: 110%; background-color: #D4F4FA; margin-top: 50px;">
    <tr>
      <td id="" style="padding: 25px 25px 10px 100px;">
        <div class="" id="">
          <button id="filePpt_0" name="filePpt_0" value="" style="font-size: xxx-large;"> 파일 다운로드 </button>
        </div>
      </td>
    </tr>
  </table>
</div>

<script type="text/javascript">

$(function(){

	$('#filePpt_0').click(function() {
		var param = "?code=";
		location.href="/myweb/downloadFile.do"+param;
	});
	
});

</script> 

</body>
</html>

 

 

 

4. FileController.java

 

location.href="/myweb/downloadFile.do"; 를 호출했을 때 실행되는 controller 를 구현한 FileController 입니다.

ResponseEntity<InputStreamResource> 를 반환값으로 한 downloadFile() 메소드를 통해 첨부파일을 다운로드 하였습니다~

 

package com.eun.myweb;

import java.io.File;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class FileController {
	
	@RequestMapping(value="/downloadFile.do")
	public ResponseEntity<InputStreamResource> downloadFile(@RequestParam String code, HttpServletResponse response, HttpServletRequest request) throws Exception {
		System.out.println("downloadFile");
		
		String filePath = "/Users/~파~일~경~로~/";  //파일 경로 
		String fileNm = "myPptFile.pptx";  //파일 이름 
		
		String fileType = fileNm.substring(fileNm.lastIndexOf(".")).trim();  //파일 형식 
		String mineType = "";

		//.equalsIgnoreCase() 를 사용하여 대소문자 구분 없이 파일 형식을 확인한다 
		if (fileType.equalsIgnoreCase(".hwp")) {
			mineType = "application/x-hwp";
		} else if (fileType.equalsIgnoreCase(".pdf")) {
			mineType = "application/pdf";
		} else if (fileType.equalsIgnoreCase(".doc") || fileType.equalsIgnoreCase(".docx")) {
			mineType = "application/msword";
		} else if (fileType.equalsIgnoreCase(".xls") || fileType.equalsIgnoreCase(".xlsx")) {
			mineType = "application/vnd.ms-excel";
		} else if (fileType.equalsIgnoreCase(".ppt") || fileType.equalsIgnoreCase(".pptx")) {
			mineType = "application/vnd.ms-powerpoint";
		} else if (fileType.equalsIgnoreCase(".zip")) {
			mineType = "application/zip";
		} else if (fileType.equalsIgnoreCase(".jpeg") || fileType.equalsIgnoreCase(".jpg") || fileType.equalsIgnoreCase(".png")) {
			mineType = "image/jpeg";
		} else if (fileType.equalsIgnoreCase(".txt")) {
			mineType = "textplain";
		}

		System.out.println("[downloadFile] fileNm : "+fileNm);

		File file = new File(filePath, fileNm);
		InputStreamResource isr = new InputStreamResource(FileUtils.openInputStream(file));
		HttpHeaders headers = new HttpHeaders();
		
		headers.setContentType(MediaType.parseMediaType(mineType));
		headers.add("Access-Control-Allow-Origin", "*");
		headers.add("Access-Control-Allow-Methods", "GET, POST, PUT");
		headers.add("Access-Control-Allow-Headers", "Content-Type");

		headers.add("Content-Disposition", "attachment; filename=" + fileNm + ";");
		headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
		headers.add("Set-Cookie", "fileDownload=true; path='/");
		headers.add("Pragma", "no-cache");
		headers.add("Expires", "0");

		headers.setContentLength(file.length());

		ResponseEntity<InputStreamResource> responseEntity = new ResponseEntity<InputStreamResource>(isr, headers, HttpStatus.OK);
		
		return responseEntity;
	}
	
}

 

 

 

안드로이드 결과화면

 

파일 다운로드 버튼 클릭 시 "파일을 다운로드합니다." 라는 토스트가 표시되고

상단바에 파일 관리자를 통해 파일 다운로드가 진행됩니다.

다운로드가 완료되면 /내장메모리/Download/ 폴더 안에 다운로드 받은 파일이 저장된 것을 확인할 수 있습니다!

 

 

 

 

 

 

 

🗳📂🗂

 

 

728x90
반응형