728x90
반응형
Java Servlet & JSP API 개발/코딩
제목 : Re: MIME타입은 주의해서 사용... 이렇게 하면 어떨지...
글쓴이: 이원영(javaservice) 2000/04/07 19:51:27 조회수:6814 줄수:176
[프린트]
손님:
> 우연치 않게 <제1회 한국 자바개발자 컨퍼런스>안내창을 보구 처음으로 이 사이트를
> 방문하게 됐습니다.......
> 
> 저는 현재 서블릿으로 게시판을 만들고 있는 서블릿 초보자입니다.
> 다른 기능들은 어느 정도 구현을 해놓았는데, 화일 다운로드에서 벽에 부딪히게 돼서
> 도움을 요청하게 됐습니다.
> 
> html, image(jpg/gif), text와 같은 화일 다운로드시 여타 응용 프로그램 화일처럼 
> 다운로드 창이 먼저 떠서 지정디렉토리에 직접 저장이 가능하게 하려구 하는데,
> 그냥 바루 웹상에 뿌려지게 되더군요!
> 
> 제가 알기로는 mime type과 관련이 있는거 같은데, 거의 모든 방법을 동원했지만
> 역부족이더군요.........^^
> 
> 고수님들의 아낌없는 조언을 부탁드립니다.....!!!


게시판의 첨부파일을 클릭할 시 저장토록하는 기능이 필요한가 보네요. 사실 이 부분은
해당 Content에 오른쪽 마우스를 누른 후 "대상 다른이름으로 저장" 을 선택하면 동일한
효과가 나타나죠..
근데, 게시판을 만드는 사람의 입장에서 생각해 보면, 사용자에게 일일이 "오른쪽 마우스
누르세요" 라고 할 수도 없고, 그래서 꼭 찍으면 "저장하기 창"이 나타나는 기능을 구현하고
싶어지게 됩니다.


먼저, 약간의 얘기를 해 보겠습니다.

*.txt 파일을 HTTP URL로 호출해 보면, 브라우져에 그 텍스트 내용이 나타납니다.
이는 웹서버의 MIME 타입에 다음과 같은 설정이 있기 때문입니다.

    text/plain          asc txt

(아파치라는 <apache>/conf/mime.typs 파일입니다. 웹서버마다 조금씩 설정방법이 다릅니다.)

또, *.exe 파일을 HTTP URL로 호출하면 "저장하기" 창이 나타납니다. 이는 MIME 타입이 아래
처럼 설정되어 있기 때문입니다.

    application/octet-stream    bin dms lha lzh exe class


서버측에서 MIME 타입이 결정나면, 웹서버는 HTTP Protocol 상의 HEADER 부분에 그 MIME을
먼저 보내고, BODY부분의 실제 데이타를 보내게 되죠.
또한 브라우져는 넘어오는 HEADER부분을 읽어서 뒤따라오는 DATA의 형식을 판단하게 됩니다.
서버에서 MIME 타입을 설정할 수 있듯이 브라우져에도 마찬가지로 MIME에 대한 적절한 반응을
어떻게 하라라는 부분이 있습니다. 대부분의 사용자는 Install할 때의 Default로 그냥 사용하죠


만약 웹서버의 MIME 타입을 약간 고쳐 보면 어떻게 될 까요? 예를 들어 아래와 같은 부분이
기본적으로 설정되어 있을 겁니다.

    text/plain          asc txt
    application/octet-stream    bin dms lha lzh exe class

여기서 txt 라는 확장자에 대한 MIME 타입을 바꾸어 보겠습니다.    

    text/plain          asc
    application/octet-stream    bin dms lha lzh exe class txt

이렇게 저장하고 웹서버를 내렸다 다시 올린 후, 브라우져에서 호출해 보면, 기존에 *.txt파일이
브라우져에서 그냥 나타났는데, 이젠 "저장하기" 창이 나타나 저장할 수 있을 겁니다.


문제는 *.txt 정도는 이렇게 할 수 있겠는데, *.html, *.gif, *.jpg 조차 바꾸어버리면 어떻게
될까요? 빈대잡으려다 초가삼간 다 태우는 격으로, 웹페이지의 모든 *.html 을 읽으려고 하면
브라우져에 나타나지 않고, "저장하기" 창만 무성하게 나타나게 되죠.

따라서 웹서버의 MIME 타입은 알려지지 않은 특정 확장자에 대해 추가적으로 조심스럽게
등록시켜 주는 정도로 사용해야 합니다. (예: *.java, *.jar, *.cpp )
저 같은 경우 *.jar 를 tar 파일과 동일하게 등록시켜뒀습니다.

    application/x-tar       tar jar

이렇게 함으로써, *.jar 파일을 클릭하면, 압축프로그램이 있다면 그 압축프로그램을 실행 할
것이고, 없다면, 저장하려 하겠죠. 만약 jar 파일에 MIME 타입을 등록시켜주지 않은 상태에서
*.jar 파일을 클릭하면 브라우져에 이상한 글자들로 막 채워 질거예요. 등록되지 않은 MIME 
타입은 기본적으로 text/plain으로 인식하거든요.

따라서 *.html, *.gif, *.jpg 등 첨부파일의 링크를 클릭했을 때, 곧바로 저장하도록 하는
방법은 단순히 MIME 타입만 변경한다고 모든 문제가 해결되지는 않아요. 오히려 엉뚱한
문제를 야기하게 되죠...

그럼 어떻게 해야 하느냐...
자바로 하기 전에 UNIX ShellScript로 CGI를 만들어 설명토록 하겠습니다.

파일로 저장되게 하는 방법은 (누군지도 모르는 PC사용자 브라우져의 MIME 타입을 강제로
변경할 방법은 없고, 결국, 서버에서 MIME 타입이 "application/octet-stream" 로 정의해서
넘겨 주는 수 밖에 없습니다. 기본적으로 브라우져는 "application/octet-stream"에 대해선
저장하도록 반응 하니까요.

(임의의 MIME 타입을 하나 만들어 보낼 수도 있습니다. 브라우져는 이해할 수 없는 MIME 타입에
대해 최초에 저장하겠느냐, 혹은 특정 어플리케이션과 연결하겠느냐 라고 묻거든요. 그러나 이건
바람직한 방법은 아니예요. 그 사람이 실수로 엉뚱한 어플리케이션과 한번 연결하면, 수동으로
고치지 않는 한 계속 그 어플리케이션이 열리게 되니까요. 어쨌거나...)

MIME 타입에 대한 얘기는 아래의 RF1521 을 보시면 잘 설명되어 있습니다
   http://freesoft.org/CIE/RFC/1521/
또, 우리가 관심이 있는 "appliction/octet-stream" 형의 MIME 타입은 아래에 설명되어 있습니다.
   http://freesoft.org/CIE/RFC/1521/32.htm

여기서 관심이 있는 부분만 보면, 만약 웹서버에서 브라우져로 데이타가 아래와 같은 형식으로
Stream이 넘어 오면 "저장하기"창이 뜬다는 것입니다.

---------------------------------------------------------------------
Content-Type: application/octet-stream
Content-Disposition: filename=hello.txt
          <---!! 반드시 빈줄이 하나이상 있어야 함
@#$#@VSGVEY#$%YVRYTY#BY$EV$%GV#YY$%YCFFW$%Y$C$%CYF#$%YT$%Y#$V$YV$#%YVW$
$%WVRV$%ER$%FV$%#TTRYBY%EYB%UR&UIIIYNUBAS$B%^&#*&$#NN#^Q@^!FTR@!^NB^@F
@^BY^E%^YG#V&^@&G@V^!BN*#*#(HBHH&RTV$%WV#$^%F^F#$@V#W$ETCF#$TRF#T#V$TC
^BTYHE$CWERWF#FCYT@$B&IM(*OP>&()P^KR*(I#G!DW%#%FGTEY@F%@D$%@D%%D@%DQ%
@^BTR#$C#RE#FDDW$R@FVTW#$TF#TFW$T@FC#$TCFV
---------------------------------------------------------------------

이제 이러한 일을 하는 Shell Script도 된 CGI 프로그램을 하나 짜볼까요?
이 CGI를 호출하면 file 파라메터로 넘어온 파일을 읽어 브라우져에서 저장시켜주는
역할을 하게 됩니다.

--------------------------------------------------------------
javaservice:/# cd /usr/local/apache/cgi-bin
javaservice:/usr/local/apache/cgi-bin# cat file.cgi
#!/bin/sh
filename=$QUERY_STRING
echo "Content-Type: application/octet-stream"
echo "Content-Disposition: filename=$filename"
echo ""
cat $filename

javaservice:/usr/local/apache/cgi-bin# chmod 755 file.cgi
javaservice:/usr/local/apache/cgi-bin# cat hello.txt
안녕하세요? 이 텍스트 파일은 브라우져에서 
저장하기 창이 팍 생겨 저장할 수 있을 거예요.
프히히....

--------------------------------------------------------------

이제, netscape를 이용해 다음 URL을 클릭해 보세요.

     http://javaservice.net/cgi-bin/file.cgi?hello.txt


NOTE: 그러나 Netscape에선 잘 동작하는 데, IE는 너무 smart(!)해서인지
      BODY 부분이 텍스트랍시고, 그냥 브라우져에 뿌려버리네요... 
      Netscape에선 잘 됩니다.

결국, 브라우져는 "아항, MIME 타입이 appliction/octet-stream 이구낭...
음, 파일이름은 'Content-Disposition: filename=' 다음에 있는 걸로 하란 소리군.."
라고 파싱을 하게 됩니다.


이러한 일련의 일을 해 주는 것을 앞에선 CGI를 이용했지만, 동일하게 자바서블렛을
이용해서도 가능합니다.
이 부분은 서블렛을 아시니 직접 해보시지요...


PS: 본 게시판도 그냥 오른쪽 마우스를 눌러 "다른 이름으로 대상 저장"를 선택하도록
    되어 있습니다. 작은 기능엔 별로 신경쓰고 싶지 않군요...
    그냥 첨부파일 링크 바로 위에 "오른쪽 마우스를 눌러 대상저장하기를 하세요"라고
    적으시면 어떨까요?

PS2 : 이러한 부분을 잘 응용하면, DB 에서 쿼리한 Data를 "application/vnd.ms-excel"
    형의 MIME 타입으로 브라우져에게 넘겨주면 브라우져는 MS-EXCEL을 기동하여
    그 데이타를 핸들링하게 할 수도 있습니다.

-------------------------------------------------------  
  본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
  이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
  이원영(javaservice@hanmail.net)
  236-1, Hyosung-2dong, Kyeyang-gu, Inchun,
  407-042, KOREA
  Phone:(82-32)540-5243, Fax:(82-32)540-5402
  PCS:019-310-7324
================================================

제목 : 성의있는 답변에 감사드립니다!
글쓴이: 황효근(guest) 2000/04/09 16:16:16 조회수:1631 줄수:25
우선 이원영님의 성의있는 답변에 대단히 감사드립니다......!!

답변해 주신 내용은 잘 읽어봤습니다....
저에게는 아주 많은 도움이 된 거 같습니다.

잘못하면 web-server의 mimetype을 건드려서 더 큰일을 낸뻔 했군요....^^;

미처 몰랐는데, 넷스케이프에서는 원래 그 기능이 지원됐었군요?

res.setContentType("application/octet-stream")
------------------------------------------------
위 처럼 설정했을 때 말이죠!

역시 익스플로러에서는 힘든가 봅니다.(서블릿으로 무단히두 애써봤지만......음)

http://altair.chonnam.ac.kr/~his/ezboard2/ezboard.cgi?db=pds&action=list&page=1

그런데, 참고로 위 사이트 게시판에서는 익스플로러에서두
*.html, *.txt, *.jpg/gif 화일들두 다운로드 창을 띄어 주더라구요?

이게 어찌된 일인지........???

암튼 다시한번 감사드립니다.....(_ _)

 
제목 : Re: 파일다운로드 창에서 열기하면 한글이 깨짐
글쓴이: 나오(guest) 2005/08/09 15:18:33 조회수:1861 줄수:116
소스입니다.   
a.jsp 에서 href를 통해 b.jsp를 엽니다.

b.jsp 내용입니다. 
(네이버 블로그 http://blog.naver.com/popo0083/40004670769   
 짜자로니(popo0083) 님 페이지에서 얻었습니다.)
<%@ page import="java.lang.*,java.util.*, java.io.*, java.sql.*"%>
<%
	String file_name = request.getParameter("file_name");
//file_name -> C:/app/aaa/web/files/vender_file/200508/E000074_20050809_6.doc
	StringTokenizer tokenF = null ;
	tokenF = new StringTokenizer(file_name,".") ;
	int ct = tokenF.countTokens();
    String[] sType = new String[ct];
	String[] rType = new String[ct];
	if (ct > 1){
		for(int j=0; tokenF.hasMoreTokens(); j++){
			sType[j] = tokenF.nextToken();
		}
		rType[1] = sType[1];
	}
	//추가	
	if(rType[1].equals("doc")){ response.setContentType("application/msword;charset=MS949"); 
	}else if(rType[1].equals("xls")){ response.setContentType("application/x-msexcel;charset=MS949");
	}else if(rType[1].equals("pdf")){ response.setContentType("application/x-msdownload");
	}else if(rType[1].equals("ppt")){ response.setContentType("application/x-mspowerpoint");
	}else if(rType[1].equals("js")){ response.setContentType("application/x-javascript");
	}else if(rType[1].equals("zip")){ response.setContentType("application/zip");
	}else if(rType[1].equals("gif")){ response.setContentType("image/gif");
	}else if(rType[1].equals("jpeg") || rType[1].equals("jpg") || rType[1].equals("jpe")){ response.setContentType("image/jpeg");
	}else if(rType[1].equals("css")){ response.setContentType("text/css");
	}else if(rType[1].equals("html") || rType[1].equals("htm")){ response.setContentType("text/html");
	}else if(rType[1].equals("xml")){ response.setContentType("text/xml");
	}else{ response.setContentType("application/octet-stream"); 
	}

	//response.setHeader("Content-Disposition", "attachment; file_name=\""+file_name+"\";");
	response.setHeader("Content-Disposition", "attachment; file_name="+file_name+";");
	//response.setHeader("Content-Transfer-Encoding", "binary;");
	response.setHeader("Content-Transfer-Encoding", "ISO-8859-1;");
	//response.setHeader("Content-Length", ""+file.length());
	response.setHeader("Pragma", "no-cache;");
	response.setHeader("Expires", "-1;"); 

    File file = new File(file_name);


	if (file.isFile())
	{
		BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream outs = new BufferedOutputStream(response.getOutputStream());
		int read = 0;
		while ((read = fin.read()) != -1)
		{
			outs.write(read);
		}
		outs.close();
		fin.close();
	}

%>



==========================  추가 끝 =================================
  해서....   a.jsp에서 href된 부분을 클릭하면 박스가 나와서 열기,저장,취소가
잘 나옵니다. 열기를 클릭하면 파일형식은 제대로 보입니다. 근데 실제 열기를 수행
하면 글자들이 깨져서 보입니다. 알수 없는 글자들....

이거 어떻게 해결할수 있는지요.

환경은 resin에서 웹,어플리케이션 서버를 돌리고 있습니다.
resin.conf에서 mime를 셋팅하는 방법도 있던데요...

네이버 블로그 
http://blog.naver.com/leejs100/20009011825 에서 퍼옴

<!--MIME Type-->  
   <mime-mapping extension='.hdml' mime-type='text/x-hdml;charset=KS_C 
    _5601-1987' /> 
   <mime-mapping extension='.wbmp' mime-type='image/vnd.wap.wbmp' />  
   <mime-mapping extension='.wml' mime-type='text/vnd.wap.wml' />  
   <mime-mapping extension='.wmlc' mime-type='application/vnd.wap.wmlc '/>  
   <mime-mapping extension='.wmlsc' mime-type='application/vnd.wap.wmls
    criptc' />  
   <mime-mapping extension='.wmls' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.wmlscript' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.ws' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.wsc' mime-type='application/vnd.wap. 
    wmlscriptc' />  
  
   <mime-mapping extension='.si9' mime-type='image/vnd.lgtwap.sis' />  
   <mime-mapping extension='.si7' mime-type='image/vnd.stiwap.sis' />  
  
   <mime-mapping extension='.nbmp' mime-type='image/nbmp' />  
   <mime-mapping extension='.sis' mime-type='image/sis' />  
   <mime-mapping extension='.si6' mime-type='image/si6' />  
   <mime-mapping extension='.toy' mime-type='image/toy' /> 
   <mime-mapping extension='.nsnd' mime-type='audio/nsnd' />  
   <mime-mapping extension='.ma1' mime-type='audio/ma1' />  
   <mime-mapping extension='.ma2' mime-type='audio/ma2' />  
   <mime-mapping extension='.pmd' mime-type='audio/pmd' />  
   <!--MIME Type--> 

이건 왑용이라서 ㅡㅡ;; j2me
저는 servlet이거든요 , j2se 저거를 resin에 추가해야한다면 좀 수정해주세요.

많은 가르침 부탁드립니다. 







728x90
반응형

+ Recent posts