HTTP download (http 파일 다운로드 하기)

개발/안드로이드 2017. 7. 27. 14:25
반응형

안녕하세요.


프로젝트에서 http에서 pdf를 다운하는 기능이 필요하여 만들게 되었습니다.

쉽게 다운로드하고 여러군데서 사용하기 위해 Manager까지 만들어 봤습니다.

까먹지 않게 기록 목적과 함께 공유하고자 허접한 코드를 올려 봅니다. 


http download 코드 자체는 간단합니다. 대충 보시면 아~ 하실껍니다.

그러나  백그라운드에서 다운받도록 하려면 쓰레드를 이용해야 합니다. 


URL oUrl;
try
{
oUrl = new URL("http://...");
HttpURLConnection oConn = (HttpURLConnection) oUrl.openConnection();
int nLen = oConn.getContentLength();
byte[] byTmpByte = new byte[nLen];
InputStream oIs = oConn.getInputStream();
File oFile = new File("downfile.dat");
FileOutputStream oFos = new FileOutputStream(oFile);

for (;;)
{
int nRead = oIs.read(byTmpByte);

if (nRead <= 0)
break;

oFos.write(byTmpByte, 0, nRead);
}

oIs.close();
oFos.close();
oConn.disconnect();
} catch (MalformedURLException e1) {
Log.e("DownloadManager", e1.getMessage());

} catch (IOException e2) {
Log.e("DownloadManager", e2.getMessage());
}



다음은 Manager 소스코드입니다. 일단 소스부터 보실까요?

public class DownloadManager extends Thread
{
public static final int HANDLE_START_DOWNLOAD = 1;
public static final int HANDLE_END_DOWNLOAD = 2;
public static final int HANDLE_FAIL_DOWNLOAD = 3;


private static DownloadManager m_oInstance = null;
private static Object m_oSync = new Object();
private String m_oStrPath = "";
private LinkedBlockingQueue<String> m_qUrl;
private boolean m_bIsThreadStoped = false;
private Thread m_pThread = null;
private Context m_oContext = null;
private boolean m_isDownload = false;

public static DownloadManager getInstance() {
synchronized (m_oSync) {

return m_oInstance;
}
}

public DownloadManager(Context _oContext)
{
m_oContext = _oContext;
m_oInstance = this;

m_qUrl = new LinkedBlockingQueue<String>(5);
m_bIsThreadStoped = false;
m_pThread = new Thread(this);
m_pThread.start();

}

public void free()
{
m_bIsThreadStoped = true;
for (int i=0; i<10; ++i)
{
try {
m_pThread.join(1000);
} catch (InterruptedException e) {

break;
}
if (!m_pThread.isAlive())
{
break;
}
}
m_pThread = null;

if (m_qUrl != null)
{
m_qUrl.clear();
m_qUrl = null;
}
m_oSync = null;
m_oInstance = null;
}

// 경로 지정.
public void setSavePath(String _strPath)
{
m_oStrPath = _strPath;
}

// URL 주소에서 파일명 가져오기
protected String getFileName(String _strUrl)
{
String[] strData = _strUrl.split("/");

if (strData.length == 0)
return "";

return strData[strData.length - 1];
}

// 다운로드 하려는 Url 지정 (여러개 한번에 지정)
public void setDownloadUrl(String[] _strUrl)
{
try
{
for (int i=0; i<_strUrl.length; ++i)
{
m_qUrl.offer(_strUrl[i], 100, TimeUnit.MILLISECONDS);
}
mmHandler.sendEmptyMessage(DownloadManager.HANDLE_START_DOWNLOAD);
}
catch (InterruptedException e)
{
Log.e("DownloadManager", "setDownloadUrl : Queue Offer Fail!!!");
}
}

// 다운로드 하려는 Url 지정.
public void setDownloadUrl(String _strUrl)
{
try
{
m_qUrl.offer(_strUrl, 100, TimeUnit.MILLISECONDS);
mmHandler.sendEmptyMessage(DownloadManager.HANDLE_START_DOWNLOAD);
}
catch (InterruptedException e)
{
Log.e("DownloadManager", "setDownloadUrl : Queue Offer Fail!!!");
}
}

public String getUrlDecode(String _strFileName)
{
String strRet = null;
try {
strRet = URLDecoder.decode(_strFileName, "UTF-8");
} catch (UnsupportedEncodingException e) {

strRet = "";
}

return strRet;
}

// 다운로드 하려는 경로 확인 후 없으면 생성..
private void checkDir()
{
File oFile = new File(getUrlDecode(m_oStrPath));
if (!oFile.exists())
oFile.mkdirs();
}

@Override
public void run() {
URL oUrl;
int nRead;
String strUrl;
HttpURLConnection oConn;
int nLen;
byte[] byTmpByte;
InputStream oIs;
File oFile;
FileOutputStream oFos;

while(!m_bIsThreadStoped)
{
try
{
strUrl = m_qUrl.poll(500, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
strUrl = null;
e.printStackTrace();
}

if (strUrl != null && strUrl.length() > 0)
{
// 다운로드 생성..
try {
checkDir();
oUrl = new URL(strUrl);
oConn = (HttpURLConnection) oUrl.openConnection();
nLen = oConn.getContentLength();
if (nLen == -1) // 사이즈를 얻어오지 못한다면 버퍼 크기를 임의로 지정.
nLen = 1000000;

byTmpByte = new byte[nLen];
oIs = oConn.getInputStream();
oFile = new File(getUrlDecode(m_oStrPath+"/"+getFileName(strUrl)));
oFos = new FileOutputStream(oFile);

for (;;)
{
nRead = oIs.read(byTmpByte);

if (nRead <= 0)
break;

oFos.write(byTmpByte, 0, nRead);
}

oIs.close();
oFos.close();
oConn.disconnect();

} catch (MalformedURLException e1) {
Log.e("DownloadManager", e1.getMessage());
mmHandler.sendEmptyMessage(DownloadManager.HANDLE_FAIL_DOWNLOAD);
} catch (IOException e2) {
Log.e("DownloadManager", e2.getMessage());
mmHandler.sendEmptyMessage(DownloadManager.HANDLE_FAIL_DOWNLOAD);
}
}
else if (m_isDownload)
{
mmHandler.sendEmptyMessage(DownloadManager.HANDLE_END_DOWNLOAD);
}

try {
Thread.sleep(200);
} catch (InterruptedException e) {
Log.e("DownloadManager", e.getMessage());
}
}
}

public Handler mmHandler = new Handler() {
public void handleMessage(Message msg) {

switch (msg.what)
{
case HANDLE_START_DOWNLOAD:
m_isDownload = true;
Toast.makeText (m_oContext, "다운로드를 시작합니다.", Toast.LENGTH_SHORT).show();

break;

case HANDLE_END_DOWNLOAD:
m_isDownload = false;
Toast.makeText (m_oContext, "다운로드를 완료하였습니다.", Toast.LENGTH_SHORT).show();

break;

case HANDLE_FAIL_DOWNLOAD:
m_isDownload = false;
Toast.makeText (m_oContext, "다운로드를 실패하였습니다.", Toast.LENGTH_SHORT).show();

break;
}
}
};
}



최대한 간단하게 사용할 수 있도록 해봤는데.. 저에게만 간단한건지 모르겠습니다. 


File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
String strDir = file.getAbsolutePath();

new DownloadManager(this.getApplicationContext());
DownloadManager.getInstance().setSavePath(strDir); // 저장하려는 경로 지정.
DownloadManager.getInstance().setDownloadUrl("http://..../file.png");

new DownloadManager(this.getApplicationContext()); 는 앱 실행 할 때 한번만 해주시면 됩니다.

그다음 은 setDownloadUrl만 호출 해주시면 다운로드가 되요~!



여러개 다운로드 하려면 배열로 할 수있도록 처리 했습니다. ~~  

String[] strUrl = new String[3];
strUrl[0] = "http://..../file1.png";
strUrl[1] = "http://..../file2.png";
strUrl[2] = "http://..../file3.png";

DownloadManager.getInstance().setDownloadUrl(strUrl); 


Manager를 프로젝트로 만들어 파일을 첨부합니다. 많은 도움이 되었으면 좋겠습니다.



HttpDownloadTest.zip










반응형
admin