관리 메뉴

새로운 시작, GuyV's lIfe sTyle.

닷넷 게시판 만들기 Part 13 - 파일 업로드 및 저장 본문

ⓟrogramming/asp.net 게시판

닷넷 게시판 만들기 Part 13 - 파일 업로드 및 저장

가이브 2011. 1. 25. 15:36

2011/01/19 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 10
2011/01/20 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 11
2011/01/21 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 12

1. 닷넷 개발환경 준비, 테스트
2. 닷넷 알아보기 [7/7]
3. asp.net 컨트롤 [4/..]


저번 시간까지 Web에서 <form>..</form>의 폼태그의 값을 닷넷 문법으로 받아봤다. 
그리고 그것을 이용해 예제로 완성물을 만들고 싶지만, 우리는 조금 바쁜 관계로(그리고 어떤 결과물은 나올 수 밖에 없으므로) 진도를 빼도록 하자.

계속해서 생각해야 할 것은 HTML의 <form>..</form>이라는 폼태그의 문법은 누가 뭐라해도 규격이 정해져있다. HTML 4.0 이라는(다음버전인 HTML5의 표준은 계속 발전중이다.) <form>태그의 값을 닷넷에서는 그것을 Request.Form / Request.QueryString 으로 값을 받아서 사용할 수 있는 것이다.

아차, 하나 빠져먹은 것이 있다. 파일 업로드!

파일 업로드를 간단하게 구현해보자. 이전 강의는 일반적인 텍스트값(텍스트 입력이든, 체크박스를하든 결국 넘기는 값은 'name=값'의 형태)인데, 파일 업로드는 조금 다르다.

바로 알아보자.
board_write.html 을 가지고 있을 것이다. 여기 맨 하단에 HTML에서 파일 컨트롤을 넣어보자. 파일 컨트롤은 <input type="file"> 이다. 물론이지만, 여기도 "name"이 들어가야 된다.

board_write.html 파일업로드 추가

<html>
<head>
<title>게시판 글쓰기</title>


</head>

<body>


<b>게시판 글쓰기 페이지</b>
<hr>

<form method="post" action="board_write_done.aspx">

 <b>이름</b>
 <input type="text" size="15" name="name">
 <hr>
 <b>제목</b>
 <input type="text" size="80" name="title">
 <hr>
 <b>글내용</b>
 <br>
 <textarea cols="80" rows="10" name="content"></textarea>
 <hr>
 <b>비밀번호</b>
 <input type="password" size="15" name="password">
 <hr>
 <b>첨부파일</b>
 <input type="file" size="15" name="uploadfile">
 <hr>
 

  <input type="submit" value="작성완료">
  <input type="button" value="취소">


</form>


</body>
</html>


진하게 표시된 부분이 파일 컨트롤이다. name은 uploadfile 이다. 
이것을 이제 온라인으로 열어보자. (127.0.0.1/board_write.html 을 브라우저로..)

하단에 "찾아보기"버튼이 달린 컨트롤이 추가되었는가? (인터넷 익스플로러 기준으로 찾아보기, 그 외의 브라우저라면 다른 문자일 수 있다. 브라우저의 재량일 뿐이다. 어쨌든 찾아보기를 누르게 되면 사용자의 컴퓨터에 있는 파일을 지정할 수 있게 된다)

파일업로드는, 텍스트 폼과 다르게, 파일컨트롤이 들어가면 <form method="post" action="board_write_done.aspx"> 항목에 추가가되어야 하는게 있다. 바로 enctype 이라는 속성이다. 이 속성은 <form>이 전송될 때 인코딩(변환)을 어떻게 하는지 추가되는데, GET과 POST는 자동으로 이 속성이 지정된다. 그러나 파일 업로드는 method 를 POST로 하여하며, 이 enctype값을 무조건 "multipart/form-data' 라고 지정해야한다.

기본으로 enctype의 값은 application/x-www-form-urlencoded 이다. 그냥 그렇구나 하시면 되며, 외울 필요 없다. :)

이제 <form..> 도 다음처럼 수정하자.
<form method="post" action="board_write_done.aspx" enctype="multipart/form-data">

HTML은 이제 완성되었으니, 이 폼 데이터를 받게되는 board_write_done.aspx 파일에서 파일을 받아보도록 하자.

이미 다루었지만, 값을 받는 클래스는 Request 이며, GET이면 Form.QueryString[""], POST면 Request.Form[""] 이렇게 받게 되는데, 파일은 어떻게 받아야 될까? 그냥 Request[""] 이렇게 받으면 되지 않을까?! 우리 생각대로 받아보자.

다음은 수정된 board_write_done.aspx 파일이다.

board_write_done.aspx

<%@ Page Language="C#" runat="server" %>

<script language="C#" runat="server">

 void Page_Load()
 {
  string name = Request["name"]; 
  string title = Request["title"]; 
  string content = Request["content"]; 
  string password = Request["password"]; 


  Response.Write("이름 : " + name + "<hr>");
  Response.Write("제목 : " + title + "<hr>");
  Response.Write("내용 : " + content + "<hr>");
  Response.Write("비번 : " + password + "<hr>");

  string file = Request["uploadfile"];
  Response.Write("업로드파일 : " + file + "<hr>");
  
}

</script>


다른 것들과 마찬가지로, 문자열 file 번수에 Request["name값"] 으로 받았다. 그리고 출력하게 된다. 이 소스의 실행 결과는 어떠한가? 앞에서 '찾아보기'로 지정한 파일의 파일명이 잘 나오는가?
왜냐하면 Request["name값"]은 단순히 그 값이 string 형으로 출력하게 된다.

파일업로드의 그 파일은 다른 형식이다.
그러므로 우리는, 일반적인 이런 <form>데이터에서의 업로드파일의 자료는 Request.Files 라는 것으로 받아야한다. (http://msdn.microsoft.com/ko-kr/library/system.web.httprequest.files(VS.80).aspx 이 MSDN 문서를 읽어보도록 하자)

Request.Files 는 속성이다. Request.Files["name값"]으로 파일을 받을 수 있는데, 이것의 클래스 형태는 HttpFileCollection(클릭시 MSDN 문서) 이다.

System.Web.HttpFileCollection 이라는 클래스명을 보면 알겠지만, 컬렉션이다.
그리고 MSDN에 설명이 다음과 같이 나와있다.

클라이언트에서 파일을 인코딩하고 multipart MIME 형식과 multipart/form-data의 HTTP Content-Type 헤더를 사용하여 콘텐츠 본문으로 파일을 전송하면, ASP.NET에서는 인코딩된 파일을 콘텐츠 본문에서 추출하여 HttpFileCollection의 개별 멤버로 만듭니다. HttpPostedFile 클래스의 메서드 및 속성에서는 각 파일의 콘텐츠 및 속성에 대한 액세스를 제공합니다.

대충 이해가 되는가? 용어가 어렵지만 어쩔 수 없다. ^__^

클라이언트트에서 파일을 인코딩하고 multipart MIME 형식과 multipart/form-data의 HTTP Content-Type 헤더를 사용하여 콘텐츠 본문으로 파일을 전송하면,
==> 파일을 전송할 수 있게 <form .. enctype="multipart/form-data">로 설정해서 넘기면,

ASP.NET에서는 인코딩된 파일을 콘텐츠 본문에서 추출하여 HttpFileCollection의 개별 멤버로 만듭니다. HttpPostedFile 클래스의 메서드 및 속성에서는 각 파일의 콘텐츠 및 속성에 대한 액세스를 제공합니다.
==> ASP.NET에서는 넘어온 값중에서 <input type='file'>인 녀석을 인식하고 HttpPostedFile 클래스의 형태로 만듭니다.

쉽게 여러분들이 이해할 수 있게 해석해보았다. 

즉, <form>..</form>태그에서 파일업로드 컨트롤인 <input type="file">이 꼭 1개만 있으라는 법은 없다. 2개이상이 있을 수 있다. 그러므로 이것은 ASP.NET을 개발한 MS에서 생각하기에, "컬렉션이면 사람들이 사용하기 좋겠다"라고 했을 것 같다. 

이론이니, 그렇게 크게 생각하지 마시고 이런 이야기를 늘여놓는 이유는, MSDN의 용어에 익숙해지라는 의미이다. 모르는 용어는 귀찮아 하지말고 전자사전 등으로 검색해서 찾아보자.

어쨌든, 설명처럼 HttpPostedFile 형태로 만든다고 하니까, 우리 예제에 적용시킨다면

HttpPostedFile file = Request.Files["uploadfile"];

이렇게 받으면 되겠다.

HttpPostedFile 의 멤버에는 무엇이 있는지 따로 꼭 읽어보도록 하자. (http://msdn.microsoft.com/ko-kr/library/system.web.httppostedfile(v=VS.80).aspx)

이 강의에서 늘 그랬듯이, MSDN에서 여러분들이 직접 HttpPostedFile 클래스의 멤버를 읽어보면, 모든 제어가 가능해지기 때문이다. :) 이 문서가 필요없을 정도로 말이다.
그러나, 초보는 홀로 코딩할 때면 언제나 막히게 된다. 될 것 같지만 막힌다. 막히면 어떻게 해라고? 더 좋아하라. 에러메시지 보기를 사랑하는 그(녀)와 같이 하라. 우리 초보는 에러메시지에 질리지말고 더 강해져야한다. 

업로드한 파일의 용량을 알아보는 프로퍼티를 찾아보자. 그리고 Response.Write() 로 찍어보자.
또한 업로드한 파일을 저장해보자. 우리의 홈 디렉터리인 c:\home 에 넘어온 파일을 저장해보자. 그리고 파일명도 찍어보도록 하자. 직접 메서드,프로퍼티를 적용시켜보고, 출력 하며 눈으로 직접 보도록 하자.

가장 중요한 것이 업로드파일의 저장이다.
일반적으로 게시판에는 파일을 첨부하는 업로드 기능이 있지 않은가?
필자는 HttpPostedFile 클래스에 SaveAs() 라는 메서드가 눈에 띄는데 여러분들은 찾으셨는가? (이미 클릭해보셨다고? 굿!) 

httpPostedFile.SaveAs(string 저장할파일명)

이라고 설명에 나와있다. 그대로 사용하면 되겠다. 이제 MSDN도 슬슬 친숙해진다는 느낌이 오지 않은가? 그렇지 않다면 어쩔 수 없다. 우리는 어떤 이유든 MSDN과 친해져야 한다.

이제 여러분들이 직접 MSDN을 참고하면서, 파일을 저장하는 코드를 짜보도록 하자.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

필자 나름대로 만든 파일 업로드 코드이다.

board_write_done.aspx (업로드 완성본)

<%@ Page Language="C#" runat="server" debug="true" %>

<script language="C#" runat="server">

 void Page_Load()
 {
  string name = Request["name"]; 
  string title = Request["title"]; 
  string content = Request["content"]; 
  string password = Request["password"]; 


  Response.Write("이름 : " + name + "<hr>");
  Response.Write("제목 : " + title + "<hr>");
  Response.Write("내용 : " + content + "<hr>");
  Response.Write("비번 : " + password + "<hr>");


  // 파일저장부분
  HttpPostedFile files = Request.Files["uploadfile"];

  string target_path = Server.MapPath("\\");   // "c:\\home"
  string file_name = files.FileName;
  files.SaveAs(target_path + @"\" + file_name); // c:\home\파일명.

  Response.Write("업로드파일 : " + file_name + "(사이즈 : " + files.ContentLength + " bytes) <hr>");
  

 }

</script>



간단하게 알아보려고 했는데, 필자 스타일이 그러지 못해 또 길어진 듯해서 사과드린다.
워낙 글주변이 없어 요약이 안되는 듯 싶다. 그러나, 여러분들께 충분히 도움되는 글일거라 믿는다.


여기까지 잘 이해하고 따라오셨다면 이제 여러분들의 상상력을 발휘하여 WebHard 를 만들어보자.
파일을 업로드하거나 삭제, 폴더를 만들거나 삭제하는 것을 웹으로 해보는 것이다.
물론, 시간이 많이 걸릴 것이고, 필자 예상에 다음의 사항들이 문제될 수 있을 것 같지만 말이다.

1. MSDN 에서 원하는 자료를 찾는 것
2. 오류 발생시 오류의 내용을 이해할 수 없는 것
3. 그냥 만들기전에 막막해 지는 것

필자가 늘 여러분들께 "생각하며 코딩하자"라는 의미는 다른게 아니라 하나하나 모르는 것을 알아가면서, 이걸 어디에 적용할 수 있으며, 어떤 것을 만들 수 있을까? 라는 생각을 말하는 것이다.

닷넷 파일 업로드는 이 허접한 글 뿐만 아니라, 어디에서든 아주 쉽게 소스까지 찾을 수 있다. 하지만 자기 기술로 만들어야 응용이 가능하다. 즉 원하는 프로그램을 만들 수 있다. 예제만 보고 따라하고 참고하는 학습 방식은, 여러분의 응용 능력에 도움이 줄 수 없다 생각한다. 또한 무언가가 되지 않을 때는 포기하는 경우도 많이 생길 것이다. 왜냐면 예제는 언제나 퍼펙트 하게 잘 돌아가기 때문이다. 이 강의에 들어가는 예제들도 필자가 직접 해보고 "되게 만든 후" 강의에 적용하기 때문에 잘 되는건 당연해 보이겠지만, 절.대 그렇지 않다. 

웹하드 만들기에 시도는 해보자. MSDN 달랑 끼고.
검색엔진에서 검색해서 소스를 참고해도 좋다.
단, 어떤 구현 방법으로 만들었는지는 꼭 알아야 할 것이다. 그런 후 또다시 혼자 만들어보도록 하자.

무엇이든 짓고 부수고 또 짓고 부수는 방법이 프로그래밍 시작에 가장 좋은 방법이라고 생각한다.


다음시간에는 asp.net 의 컨트롤은 <form>태그와 어떤점이 다른지 알아보겠다.
그러나, 늘 말씀드리지만 asp.net 의 결과물은? 태그일 뿐이다. :)
외우고 자시고 할 것도 없으니, 어떻게 사용하고 HTML과 연계시키는지만 알면 된다.


다음시간에..


반응형
Comments