서버에 동영상 파을일 업로드하는 모듈을 개발중인데요
어느정도 작은 용량의 파일은 업로드가 되는데,
용량이 조금만 커져도 업로드를 진행하다가 메모리 오류가 나네요.
혹시 이런 문제 해결해 보신분 계신가요?
아래는 에러 로그 이구요.
03-22 17:34:35.176: E/dalvikvm-heap(29528): Out of memory on a 16775354-byte allocation.
03-22 17:34:35.186: E/dalvikvm(29528): Out of memory: Heap Size=23111KB, Allocated=11374KB, Bitmap Size=4500KB, Limit=36864KB
03-22 17:34:35.186: E/dalvikvm(29528): Extra info: Footprint=23111KB, Allowed Footprint=23111KB, Trimmed=868KB
03-22 17:34:35.196: W/dalvikvm(29528): threadid=11: thread exiting with uncaught exception (group=0x4001d5a0)
03-22 17:34:35.216: E/AndroidRuntime(29528): java.lang.RuntimeException: An error occured while executing doInBackground()
03-22 17:34:35.216: E/AndroidRuntime(29528): java.lang.RuntimeException: An error occured while executing doInBackground()
03-22 17:34:35.216: E/AndroidRuntime(29528): at android.os.AsyncTask$3.done(AsyncTask.java:200)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.lang.Thread.run(Thread.java:1027)
03-22 17:34:35.216: E/AndroidRuntime(29528): Caused by: java.lang.OutOfMemoryError: (Heap Size=23111KB, Allocated=11374KB, Bitmap Size=4500KB)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:216)
03-22 17:34:35.216: E/AndroidRuntime(29528): at org.apache.harmony.luni.internal.net.www.protocol.http.RetryableOutputStream.write(RetryableOutputStream.java:60)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.io.DataOutputStream.write(DataOutputStream.java:99)
03-22 17:34:35.216: E/AndroidRuntime(29528): at 패키지명.participation$Upload.doInBackground(participation.java:527)
03-22 17:34:35.216: E/AndroidRuntime(29528): at 패키지명.participation$Upload.doInBackground(participation.java:1)
03-22 17:34:35.216: E/AndroidRuntime(29528): at android.os.AsyncTask$2.call(AsyncTask.java:185)
03-22 17:34:35.216: E/AndroidRuntime(29528): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
03-22 17:34:35.216: E/AndroidRuntime(29528): ... 4 more
03-22 17:34:35.727: E/WindowManager(29528): Activity 패키지명.participation has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4063f668 that was originally added here
03-22 17:34:35.727: E/WindowManager(29528): android.view.WindowLeaked: Activity 패키지명.participation has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4063f668 that was originally added here
03-22 17:34:35.727: E/WindowManager(29528): at android.view.ViewRoot.<init>(ViewRoot.java:275)
03-22 17:34:35.727: E/WindowManager(29528): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
03-22 17:34:35.727: E/WindowManager(29528): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
03-22 17:34:35.727: E/WindowManager(29528): at android.view.Window$LocalWindowManager.addView(Window.java:430)
03-22 17:34:35.727: E/WindowManager(29528): at android.app.Dialog.show(Dialog.java:288)
03-22 17:34:35.727: E/WindowManager(29528): at 패키지명.participation$Upload.onPreExecute(participation.java:461)
03-22 17:34:35.727: E/WindowManager(29528): at android.os.AsyncTask.execute(AsyncTask.java:391)
03-22 17:34:35.727: E/WindowManager(29528): at 패키지명.participation$10.onClick(participation.java:289)
03-22 17:34:35.727: E/WindowManager(29528): at android.view.View.performClick(View.java:2532)
03-22 17:34:35.727: E/WindowManager(29528): at android.view.View$PerformClick.run(View.java:9277)
03-22 17:34:35.727: E/WindowManager(29528): at android.os.Handler.handleCallback(Handler.java:587)
03-22 17:34:35.727: E/WindowManager(29528): at android.os.Handler.dispatchMessage(Handler.java:92)
03-22 17:34:35.727: E/WindowManager(29528): at android.os.Looper.loop(Looper.java:143)
03-22 17:34:35.727: E/WindowManager(29528): at android.app.ActivityThread.main(ActivityThread.java:4196)
03-22 17:34:35.727: E/WindowManager(29528): at java.lang.reflect.Method.invokeNative(Native Method)
03-22 17:34:35.727: E/WindowManager(29528): at java.lang.reflect.Method.invoke(Method.java:507)
03-22 17:34:35.727: E/WindowManager(29528): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-22 17:34:35.727: E/WindowManager(29528): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-22 17:34:35.727: E/WindowManager(29528): at dalvik.system.NativeStart.main(Native Method)
다음은 해당 소스 부분 입니다.
// 확인 버튼
btn_submit.setOnClickListener(new OnClickListener(){
public void onClick(View v){
btn_submit.setClickable(false);
// 신규 등록 이면
if(Global.Upload_State.equals("New")){
if ( txt_path.getText().equals("") ){
Dialog("업로드할 동영상이 필요합니다.");
}else{
if ( (edit_title.getText().toString().equals("")) || (edit_content.getText().toString().equals("")) || (edit_keyword.getText().toString().equals("")) ) {
Dialog("모든 항목을 빠짐 없이 작성해 주세요.");
} else {
// 업로드
new Upload().execute("인수", "경과값", "업로드 중 입니다."); ////////////////// 289 번 라인
}
}
// 수정 이면
}else if(Global.Upload_State.equals("Modify")){
if ( (edit_title.getText().toString().equals("")) || (edit_content.getText().toString().equals("")) || (edit_keyword.getText().toString().equals("")) ) {
Dialog("모든 항목을 빠짐 없이 작성해 주세요.");
} else {
// 업로드(수정)
// 동영상 파일포함한 수정 이면
if( !txt_path.getText().equals("") ){
ArrayList<NameValuePair> httpParams = new ArrayList<NameValuePair>();
httpParams.add(new BasicNameValuePair("album", Global.idx));
httpParams.add(new BasicNameValuePair("mode", "D"));
String tmpData = cmsHttp.sendPost(Global.FileDel_URL, httpParams);
switch(Parser.Parsing_OnlyResult(tmpData)){
case 1:
Log.i(tag, Global.idx+" 삭제.");
new Update().execute("인수", "경과값", "수정을 위해 신규 영상을 업로드중 입니다.");
break;
case 2:
Log.i(tag, Global.idx+" 삭제실패.");
Dialog("게시물 수정 실패");
break;
default:
Dialog("처리 과정중 문제가 발생 했습니다.");
break;
}
// 동영상 파일 없이 정보만 수정하는 경우
}else{
new Update().execute("인수", "경과값", "수정 중 입니다.");
}
}
}
}
});
/* AsyncTask로 파싱 (신규등록) */
class Upload extends AsyncTask<String, Integer, String> { //인수, 경과값, 결과값
// 작업이 시작되기전에 호출
protected void onPreExecute() {
dialog = new ProgressDialog(participation.this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage("Loading...");
dialog.setIndeterminate(false);
dialog.setCancelable(false);
dialog.setProgress(0);
dialog.setMax(100);
dialog.setSecondaryProgress(0);
//dialog.setButton("취소", new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int whichButton) {
// cancel(true);
// }
//});
dialog.show(); //////// 461 번 라인
}
// 스레드에서 실행
protected String doInBackground(String... strData) {dialog.setMessage(strData[2]); cmsHttp cmsHttp = new cmsHttp(); cmsHttp.act = participation.this;
// 업로드 할 파일의 고유값 생성 요청
String tmpData = cmsHttp.sendGet(Global.Upload_Init_URL);
// 요청결과에서 고유값 파싱
String Init_resut = Parser.ParsingJson_Init(tmpData);
if(Init_resut.equals("true")){
Log.i(tag, "Global.idx : "+Global.idx);
// 파일 업로드
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try {
FileInputStream mFileInputStream = new FileInputStream(new File(Global.folder_addrs, Global.filename));
URL connectUrl = new URL("Global.Upload_File_URL + "&album=" +Global.idx);
Log.i("HttpFileUpload", "mFileInputStream is " + mFileInputStream);
// open connection
HttpURLConnection conn = (HttpURLConnection)connectUrl.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
Log.i(tag, "album_idx : "+Global.idx + " filename : " + Global.filename);
// write data
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"filename\";filename=\"" + Global.filename+"\"" + lineEnd);
//dos.writeBytes("Content-Disposition: form-data; album=\"" + Global.idx + "\"; filename=\"" + fileName+"\"" + lineEnd);
dos.writeBytes(lineEnd);
//
int bytesAvailable = mFileInputStream.available();
int maxBufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
int bytesRead = mFileInputStream.read(buffer, 0, bufferSize);
Log.i("HttpFileUpload", "file byte is " + bytesRead);
float filesize = bytesAvailable;
float percent = 0;
// read data
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize); ///////// 527번 라인
bytesAvailable = mFileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = mFileInputStream.read(buffer, 0, bufferSize);
Log.i("파일변환중", "bytesAvailable : "+bytesAvailable);
if(bytesAvailable > 0){
percent = Float.valueOf(bytesAvailable).floatValue() / filesize * 100;
int p = 100 - (int)percent;
publishProgress(p);
}
}



잘게 쪼개서 조금씩 보내고.. 서버에서는 조각조각 받아서 원래대로 붙이는 방법으로 해야겠죠.