2009년 11월 10일 화요일

ASP :: 파일 업로드/다운로드 구현하기

출처 : ASP 학습 ( http://flashcafe.org/asp_study/3895/page/3 )


인터넷에는 매우 많은 파일 업로드 관련 컴포넌트가 떠돌아다니고 있다. 어떤 것들은 비용을 지불하고 구입해야 하는 것도 있으며,어떤 것은 공짜로 기능에 제한 없이 사용하는 것들도 있다. 이번에 설명하는 파일 업로드/다운로드 구현은 SiteGalaxytUpload 라는 컴포넌트를 이용하여 파일 업로드를 구현하는 방법을 설명하도록 한다.
이 컴포넌트는 ASP 기반 자료실을 제작하는 데 많은 도움이 될 것이다.





● 왜 파일 업로드는 별도로 제공되는 컴포넌트를 사용해야 하는가?


애석하게도, FileSystemObject나 ADODB.RecordSet 등을 통해서는 파일 업로드를 직접 구현할 수 없다. 왜냐하면, 파일을 서버에 보내기 위해서는 FORM 태그에서 ENCTYPE="multipart/form-data"라는 속성을 넣어 주어야 하는데, 이렇게 되면 ASP에서는 Request.Form 개체를 사용하지 못하게 된다.


결국, 파일을 업로드하기 위해서는 파일도 받아들일 수 있고, 입력 양식 데이타도 동시에 받아들일 수 있는 기능을 가진 별도의 컴포넌트를 이용해야 한다. 이를 위하여, 인터넷 상에는 파일 업로드를 구현해 주는 수 많은 컴포넌트가 있는데, 그 중 우리는 사용하기 쉬운 SiteGalaxyUpload 라는 이름의 컴포넌트를 사용해 보도록 한다.





● SiteGalaxyUpload 사용방법


1) SiteGalaxyUpload 컴포넌트 설치



  1. 먼저, 파일(SiteGalaxyUpload.zip, 169 KB)을 다운로드 받는다.
  2. 다운받은 파일을 C:\Windows\System32 폴더에 복사한다.
  3. 작업 표시줄의 [시작] → [실행]을 클릭한다. 그리고 아래와 같이
    regsvr32 SiteGalaxyUpload.dll 을 입력하고 [확인]을 누른다

    (추가1)
    SiteGalaxyUpload.dll 파일!  

    아래 파일을 설치후에 첨부 DLL 파일을 c:\windows\system32 에 다운 후,
    시작 ->실행-> regsvr32 sitegalaxyupload.dll 엔터

    ##### OPEN #####

    참고로 SiteGalaxyUpload.dll 파일의 속성에서 Everyone 이 추가되어야 게시판 글 등록이 가능합니다.




  4. 4번의 과정이 성공적으로 이루어졌으면 아래와 같은 메세지를 볼 수 있다.

    "DllRegisterServer in c:tempSiteGalaxyUpload.dll succeeded."

    이 메세지는 윈도우즈 레지스트리에 컴포넌트 정보가 이상없이 등록되었다는 뜻이며 이것으로 컴포넌트 설치는 완료된 것이다.

2) 파일 업로드 페이지 제작


아래와 같이 HTML 문서를 만들고, upload.htm 이라는 이름으로 저장한다.


<HTML>
<BODY>
<FORM METHOD=POST ACTION=upload.asp ENCTYPE="multipart/form-data">
<INPUT TYPE=FILE NAME=FILE1 VALUE="검색..."><P>
<INPUT TYPE=SUBMIT VALUE="파일 업로드">
</FORM>
</BODY>
</HTML>

그 다음은, 파일을 업로드하는 upload.asp를 아래와 같이 작성한다.


<%
Set uploadForm = Server.CreateObject("SiteGalaxyUpload.Form")
Set fso = Server.CreateObject("Scripting.FileSystemObject")
uploadForm("FILE1").SaveAs( _
"c:temp" & fso.GetFileName(uploadForm("FILE1").FilePath))
Response.Write("File Upload Success!")
%>

이제, 예제를 테스트 해 본다. 먼저, upload.htm을 웹 브라우저로 연다.




[찾아보기...]버튼을 눌러 나타나는 대화 상자에서, 아무 파일이나 하나 선택한다.
여기서는 C:bootlog.txt 파일을 첨부해보도록 한다.




이제, [파일 업로드] 버튼을 누르면, 파일이 웹 서버에 업로드된다. 이 파일이 제대로 업로드 되었는가를 확인하려면 탐색기에서 C:TEMP 디렉토리를 찾아가 확인하면 된다.





● 간단한 자료실 만들기


실제 자료실은, 단순히 파일만 업로드하고 다운로드하는 것이 아니라, 업로드된 파일에 대한 각종 정보가 관리되는 일종의 게시판 기능이 들어가야 한다.
이번에는, 파일 업로드 기능 및 다운로드 기능이 구현된 간단한 자료실을 구축하는 예를 들어보도록 한다.


먼저, 자료실에 파일을 업로드하는 HTML 문서는 앞서 설명한 페이지를 약간 수정해서 제작한다. 자료실에 업로드될 파일에 대한 정보를 기록하는 입력 양식을 추가하도록 한다.


1) Upload.htm
아래는 새로 바뀌는 upload.htm 이다.






<HTML>
<HEAD><TITLE>자료 업로드</TITLE></HEAD>
<BODY BGCOLOR=ffffff>
<CENTER>
<H1>자료 업로드</H1>
<A HREF=ViewList.asp>목록 보기</A>
<HR>
<FORM METHOD=POST ACTION=upload.asp ENCTYPE="multipart/form-data">
<TABLE BORDER=0 ALIGN=CENTER>
<TR>
<TD>자료 제목 : </TD>
<TD><INPUT TYPE=TEXT NAME=TITLE SIZE=30></TD>
</TR>
<TR>
<TD COLSPAN=2>자료 설명 : <BR>
<TEXTAREA NAME=DESC ROWS=10 COLS=50 WRAP=OFF></TEXTAREA></TD>
</TR>
<TR>
<TD COLSPAN=2><INPUT TYPE=FILE NAME=FILE1 VALUE="검색..."></TD>
</TR>
<TR>
<TD COLSPAN=2><INPUT TYPE=SUBMIT VALUE="파일 업로드"></TD>
</TR>
</TABLE>
</FORM>
</CENTER>
</BODY>
</HTML>



 


2) Upload.asp
이제 upload.asp를 수정하자. upload.asp는 파일 업로드 기능 및 위의 입력 양식에서 입력된 파일에 대한 정보들을 입력받아 [방명록 만들기]에서 본 FileSystemObject 개체를 이용하여 목록 파일을 만들 수 있는 기능이 추가된다.






<%

' Program Name : Upload.asp

Dim uploadform
Dim fso
Dim f
Dim id
Dim myLine

Set uploadform = Server.CreateObject("SiteGalaxyUpload.Form")

' Upload를 수행한다.
If Trim(uploadform("TITLE")) = "" Or _
Trim(uploadform("DESC")) = "" Or _
uploadform("FILE1").Size = 0 Then
Call NoRequiredField
Else
FilePath = "d:dataasptutuploadupload_data"
ListPath = "d:dataasptutuploadupload_list"

' id.txt를 열어 등록된 자료건수를 1 증가시키고 저장한다.
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Set id = fso.OpenTextFile(ListPath & "id.txt")
NewID = id.ReadLine
NewID = NewID + 1
Set id = Nothing
Set id = fso.CreateTextFile(ListPath & "id.txt", True)
id.WriteLine NewID
Set id = Nothing

' 업로드된 파일을 다른 이름으로 저장한다.
uploadform("FILE1").SaveAs(FilePath & NewID & "." & _
fso.GetExtensionName(uploadform("FILE1").FilePath))

' 입력 양식으로 넘어온 정보들을 가지고 자료실 목록 파일을 만든다.
Set f = fso.CreateTextFile(ListPath & NewID & ".txt", True)
f.WriteLine uploadform("TITLE")

' 파일명
f.WriteLine fso.GetFileName(uploadform("FILE1").FilePath)

' 다른 이름으로 저장된 파일명
f.WriteLine FilePath & NewID & "." & _
fso.GetExtensionName(uploadform("FILE1").FilePath)

' MIME HEADER
f.WriteLine uploadform("FILE1").MimeType & "/" & _
uploadform("FILE1").MimeSubtype

' 파일크기
f.WriteLine uploadform("FILE1").Size

' 조회수
f.WriteLine "0"

' Download수
f.WriteLine "0"

' 파일에 대한 설명
f.WriteLine Replace(uploadform("DESC"), vbCr, "<BR>")

Set f = Nothing
Set fso = Nothing
Call OK
End If

Set uploadform = Nothing

Sub NoRequiredField
Response.Write "<HTML>"
Response.Write "<HEAD><TITLE>Error</TITLE></HEAD>"
Response.Write "<BODY BGCOLOR=ffffff>"
Response.Write "<H1>Error!</H1>"
Response.Write "<HR>"
Response.Write "자료, 자료 제목, 자료 설명은 반드시 입력하셔야 합니다."
Response.Write "확인하시고 다시 입력해 주십시오.<P>"
Response.Write "<A HREF=javascript:history.back()>Back</A>"
Response.Write "</BODY></HTML>"
End Sub

Sub OK
Response.Write "<HTML>"
Response.Write "<HEAD><TITLE>Success</TITLE></HEAD>"
Response.Write "<BODY BGCOLOR=ffffff>"
Response.Write "<H1>Success!</H1>"
Response.Write "<HR>"
Response.Write "File Upload에 성공하였습니다.<P>"
Response.Write "<A HREF=ViewList.asp>목록 보기</A>"
Response.Write "</BODY></HTML>"
End Sub
%>

자료실 목록에 관련된 파일들은 모두 ListPath 변수에 지정된 디렉토리에, 실제 업로드되는 파일들은 모두 FilePath 변수에 지정된 디렉토리에 저장되게 된다. 이 변수들은 나머지 ASP 프로그램에도 똑같이 적용된다.
SiteGalaxy.Form 개체가 생성되면 위와같이 컬렉션의 형태로 입력 양식의 값들을 참조할 수 있다. 그런데, 하나 주의할 점은 HTML 입력 양식에서 정의된 입력 양식 이름(NAME 속성)과 컬렉션을 참조하는 키(Key) 값은 대소문자를 구분한다는 점이다.


즉, HTML 입력 양식에



<INPUT TYPE=FILE NAME=FILE1>


이라고 정의해 놓고



uploadform("file1")


을 참조하게 되면 에러가 발생한다. 반드시 uploadform("FILE1") 으로 수정해 주어야 한다. 이는 SiteGalaxyUpload 컴포넌트 자체의 버그인 것 같다.
그 외, 목록 파일을 만드는 기법은 지난번에 설명한 파일 시스템 기반 방명록과 다를 것이 없다.


3) ViewList.asp
다음은, 목록 파일들의 리스트를 보여주는 ViewList.asp의 소스이다.






<%

' Program Name : ViewList.asp

Dim fArray
Set fso = Server.CreateObject("Scripting.FileSystemObject")
ListPath = "d:Dataasptutuploadupload_list"
Set fldr = fso.GetFolder(ListPath)
Set fc = fldr.Files
For Each fn in fc
If fn.Name <> "id.txt" Then
fNames = fNames & "/" & fn.Name
End If
Next
fArray = Split(fNames, "/")

Response.Write "<HTML>"
Response.Write "<HEAD><TITLE>자료실</TITLE></HEAD>"
Response.Write "<BODY BGCOLOR=ffffff>"
Response.Write "<CENTER><H1>자료실</H1>"
Response.Write "<A HREF=upload.htm>업로드</A>"
Response.Write "<HR>"
Response.Write "<TABLE BORDER=1>"
Response.Write "<TR>"
Response.Write "<TH>제목</TH><TH>파일명</TH><TH>SIze</TH>"
Response.Write "<TH>조회</TH><TH>Download</TH>"
Response.Write "</TR>"

For i = UBound(fArray) To 1 Step -1
Set f = fso.OpenTextFile(ListPath & fArray(i))
Call PrintList(Left(fArray(i), Len(fArray(i)) - 4), _
f.ReadLine, f.ReadLine, f.ReadLine, f.ReadLine, f.ReadLine, f.ReadLine, f.ReadLine)
Next

Response.Write "</TABLE><P>"
Response.Write "<A HREF=upload.htm>업로드</A>"
Response.Write "</CENTER>"
Response.Write "</BODY>"
Response.Write "</HTML>"

Set fc = Nothing
Set fldr = Nothing
Set fso = Nothing

Sub PrintList(id, title, filename, realfilename, mimeheader, filesize, read, download)
Response.Write "<TR><TD>" & title & "</TD>"
Response.Write "<TD><A HREF=ViewDetail.asp?id=" & id & ">" & filename & "</A></TD>"
Response.Write "<TD ALIGN=RIGHT>" & filesize & "</TD>"
Response.Write "<TD ALIGN=RIGHT>" & read & "</TD>"
Response.Write "<TD ALIGN=RIGHT>" & download & "</TD></TR>"
End Sub
%>

아래는 ViewList.asp의 실행 결과이다.




ViewList.asp는 이전에 설명했던 방명록 목록보기 소스를 약간 수정한 것 밖에 없다.


4) ViewDetail.asp
이제는, 자료실의 목록을 클릭했을 때 다운로드 받을 수 있도록 하는 ViewDetail.asp 를 제작하도록 한다.






<%

' Program Name : ViewDetail.asp

Set fso = Server.CreateObject("Scripting.FileSystemObject")
ListPath = "d:Dataasptutuploadupload_list"
Set f = fso.OpenTextFile(ListPath & Request.QueryString("id") & ".txt")
title = f.ReadLine
filename = f.ReadLine
realfilename = f.ReadLine
mimeheader = f.ReadLine
filesize = f.ReadLine
read = f.ReadLine
download = f.ReadLine

' ReadAll 메소드보다는 이런 방법을 사용할 것을 권장한다.
Do While f.AtEndOfLine <> True
desc = desc & f.ReadLine
Loop

Set f = Nothing

' 조회건수를 증가시키고 파일에 저장한다.
Set f = fso.CreateTextFile(ListPath & Request.QueryString("id") & ".txt", True)
read = read + 1
f.WriteLine title
f.WriteLine filename
f.WriteLine realfilename
f.WriteLine mimeheader
f.WriteLine filesize
f.WriteLine read
f.WriteLine download
f.WriteLine desc
Set f = Nothing

' 자료에 대한 상세정보를 표시하고 다운로드 받을수 있도록 한다.
Response.Write "<HTML>"
Response.Write "<HEAD><TITLE>자료실</TITLE></HEAD>"
Response.Write "<BODY BGCOLOR=ffffff>"
Response.Write "<CENTER><H1>자료실</H1>"
Response.Write "<A HREF=upload.htm>업로드</A> "
Response.Write "<A HREF=ViewList.asp>목록 보기</A>"
Response.Write "<HR>"
Response.Write "<TABLE BORDER=1>"
Response.Write "<TR><TD>제목</TD><TD>" & title & "</TD></TR>"
Response.Write "<TR><TD>파일명</TD><TD>" & filename & "</TD></TR>"
Response.Write "<TR><TD>Size</TD><TD>" & filesize & "</TD></TR>"
Response.Write "<TR><TD>조회</TD><TD>" & read & "</TD></TR>"
Response.Write "<TR><TD>Download</TD><TD>" & download & "</TD></TR>"
Response.Write "<TR><TD COLSPAN=2>"
Response.Write "<A HREF=Download.asp?id=" & Request.QueryString("id") & ">"
Response.Write "Click Here To Download" & "</A></TD></TR>"
Response.Write "<TR><TD COLSPAN=2>" & desc & "</TD></TR>"
Response.Write "</TABLE>"
Response.Write "</CENTER></BODY></HTML>"
%>

위의 소스에서는, 지금까지 썼던 ReadAll 메소드 대신에 TextStream 개체의 AtEndOfLine 속성을 이용한 것을 볼 수 있다.
사 실, ReadAll 메소드에는 약간의 버그가 있는데, 항상 마지막 라인에 vbCr 문자를 꼭 추가해서 문자열에 저장하는 점이 문제가 된다. 이렇게 되면 계속해서 ViewDetail.asp가 호출될 때마다 목록 파일의 끝에는 vbCr 문자가 계속해서 더해지게 되므로, 파일 저장시 쓸데없는 개행 문자들이 늘어난다는 문제가 있어서 부득이하게 이러한 방법을 사용하였다.


아래는 ViewDetail.asp의 실행 결과이다.





5) Download.asp
이제 마지막으로, Download.asp를 제작한다.
SiteGalaxyUpload.FileSystemObject 개체에는 OpenBinaryFile 이라는 메소드가 있는데, 이 메소드와 Response 개체의 BinaryWrite 메소드를 이용하면 파일 시스템으로부터 파일을 다운로드 받을 수 있다. 이미, upload.asp에서 해당하는 파일의 MIME 헤더를 목록 파일에 기록해 놓아 두었으므로, 그에 따라 Response.ContentType을 지정해서 클라이언트에 MIME 헤더를 내려 보낼 수 있다. 그리고, 다운로드 될 때는 다운로드 횟수를 조회수를 증가시키는 방법을 이용해서 1씩 증가시킨다. 아래는 소스이다.






<%

' Program Name : Download.asp

ListPath = "d:Dataasptutuploadupload_list"

Set fso = Server.CreateObject("Scripting.FileSystemObject")

' 목록 파일을 열고 정보를 가져온다.
Set f = fso.OpenTextFile(ListPath & Request.QueryString("id") & ".txt")
title = f.ReadLine
filename = f.ReadLine
realfilename = f.ReadLine
mimeheader = f.ReadLine
filesize = f.ReadLine
read = f.ReadLine
download = f.ReadLine

Do While f.AtEndOfLine <> True
desc = desc & f.ReadLine
Loop
Set f = Nothing

' Download 건수를 증가시키고 파일에 저장한다.
Set f = fso.CreateTextFile(ListPath & Request.QueryString("id") & ".txt", True)
download = download + 1
f.WriteLine title
f.WriteLine filename
f.WriteLine realfilename
f.WriteLine mimeheader
f.WriteLine filesize
f.WriteLine read
f.WriteLine download
f.WriteLine desc

Set f = Nothing
Set fso = Nothing

' SiteGalaxyUpload.FileSystemObject 객체를 생성한다.
Set fso = Server.CreateObject("SiteGalaxyUpload.FileSystemObject")

Response.Expires = 0
Response.Buffer = True
Response.Clear

' MIME Header를 목록 파일에 등록된 값으로 설정한다.
Response.ContentType = mimeheader

' OpenBinaryFile 메소드를 이용해서 파일 시스템의 파일을 가져온다.
Set f = fso.OpenBinaryFile(realfilename, 1, False)

' BinaryWrite 메소드를 이용해서 클라이언트에 자료를 전송한다.
Response.BinaryWrite f.ReadAll
Response.End

Set f = Nothing
Set fso = Nothing
%>




이 강좌 한 Chapter를 만들기 위해서 참 여러곳을 뒤졌다. 파일 업로드에 관련된 여러가지 컴포넌트를 테스트해 볼 수 있었던 시간이었는데 마음에 드는 것을 고르기가 참 힘들었다. 하지만, 위의 소스만으로도 조금만 응용하면 멋진 ASP기반 자료실을 구축하는데는 많은 도움이 될 것이다.


댓글 2개:

  1. 안녕하세요 질문이 있는데요. 위에 컴포넌트 설치를 해야 된다고 하셧는데 그걸 서버에 설치하는건가요? 아니면 작업 PC 아니면 사용자 PC 인가요?

    답글삭제
    답글
    1. 당영히 서버에 설치해야됩니다. ^^

      삭제