login register Sysop! about ME  
qrcode
    최초 작성일 :    2001년 11월 01일
  최종 수정일 :    2001년 11월 14일
  작성자 :    taeyo
  편집자 :    Taeyo (김 태영)
  읽음수 :    142,743

강좌 목록으로 돌아가기

필자의 잡담~

정말로 오랜만의 강좌입니다. 죄송하네요... T.T.. 정말루 잘 해야하는데... 히~~~
괜히 테러까지 난 미국에 와서리... 탄저병의 공포에 시달리면서, 집안에서 뒹굴뒹굴...
인터넷이 안되서 강좌를 못 올렸다는 변명밖에는 드릴 것이 없네요.. 받아주세요 ^^

너무 오랜만에 쓰는 강좌이기에 죄송한 마음을 가지고 강좌를 쓰고 있습니다. 한달 넘게 강좌를 올리지 않다보니 많은 생각을 하게 되기도 하더라구요..  언젠가부터 강좌를 의무감에 쓰기 시작했다는 사실이 스스로에게 부담감으로 느껴지기도 하구, 그런 식으로 준비한 강좌는 정말루 가려운 곳을 긁어주는 강좌가 되지 못하는 것같다는 주제파악까지 하게 되기도 했죠..

남에게 보여줄라구 준비하는 글은 조금은 포장된 느낌이기에 싫어했는데, 언젠가부터 그런 강좌를 써온 것은 아니었나하는 생각이 듭니다. 하긴 아무래도 처음 사이트를 열고, 강좌를 쓸 때와 지금은 많은 것이 달라졌으니...  예전같을 수는 없겠구나.. 하는 생각도 드네요... 나쁜 점만 있는 것은 아니긴 하지만..  -_-;

하지만, 예나 지금이나 달라지지 않은 것이 있다면 그것은... 바로 이것!! 강좌를 시작하기 전에 여전히 사설이 많다는 것입니다. 뭔 할 이야기가 그리도 많은지 언제나 이렇게 주절주절...  그것 참...

이전 강좌에서 ABCUpload 를 가볍게 다루어 보았으니 이제 그 지식을 기반으로 현재까지 만든 게시판에 자료실 기능도 한번 붙여보도록 하겠습니다. ^^  게시판이 자료실로 거듭나기 위해서 외형상 그다지 많이 바꿀 것은 없습니다. 단지, 글 쓰는 폼에 업로드할 파일을 선택할 수 있도록 [파일선택] 컨트롤을 하나 추가해 주면 되는 것이지요. 디자인이 좀 썰렁하기는 하지만, 다음처럼 말입니다 ^^

기존의 폼 중간에 파일을 선택하는 <Input type="file".. > 컨트롤을 하나 추가해 준 것을 볼 수 있죠? 여러분도 그렇게 추가해 주시면 됩니다. 저의 경우는 소스중에 다음처럼 추가했습니다. 대략 68 line 즈음에 말입니다요. ^^

<tr>
    <td align="right" >파일첨부</td>
    <td align="left" style="padding-left: 20; padding-right: 30">
             <input type="file" name="attachFile" style="color:slategray;border:1 solid silver;width:300; height:20"> (최대 4M)</td>
</tr>

음하하..  이러면  모든 준비가 끝난 것이냐? 설마...  역시 여러분은 여전히 예리함이 살아있습니다. 대단합니다. 오호라..~~~   아직 여러가지의 준비사항이 남아있는 것이었습니다.

우선, 폼에 Encoding 속성을 설정해야 합니다. 이미 이전 강좌에서 설명드린 것처럼 말입니다. 해서 여러분은 폼코드에다가 인코드 설정을 추가하기 위해서 다음처럼 해주시면 된답니다.

<form method="POST" action="Insert.asp" name="myform" enctype="multipart/form-data">

enctype 를 추가한 것이지요 ^^

이제 글쓰는 폼에다가 파일을 업로드할 수 있는 기능은 달아두었습니다.

이제는 파일이 업로드될 폴더를 하나 만들어서 지정해야 합니다. 실제 태오 사이트의 경우는 따로 가상 디렉토리를 하나 만들어서 그 구역에 파일을 업로드하도록 구성했습니다. C 드라이브는 루트 드라이브이기에 공간이 넉넉해야 하니깐, 제 사이트의 경우는 E 드라이브에 그러한 공간을 준비했지요.

하지만, 우리의 예제에서는 그냥 현재 게시판용 디렉토리의 하위로 디렉토리를 하나 만들고, 그 곳에 파일을 업로드 하도록 꾸며보려 합니다. 폴더의 이름은 다같이.. 즐거운 마음으로  Uploaded_Files 라는 이름으로 합시다. 이유는? ...  음....  그냥..  ^^

저의 경우는 지금 이 게시판이 Web 이라는 가상디렉토리에 존재하고 있거든요..  다시 말해서리 이 강좌를 위해서 같이 만들고 있는 이 샘플 파일들을 제 로컬서버에다가 Web 이라는 가상 디렉토리를 만들고 그 안에 게시판 파일들을 두었다는 이야기입니다. 즉, 제 가상디렉토리의 실제 위치는 C:\Inetpub\wwwroot\Web 이라는 것이지요. 거기다가 하위로 Uploaded_Files 라는 폴더를 만들었다는 의미입니다.

하지만, 여러분은 지금 이 게시판을 만들어서 테스트하고 있는 폴더의 하위로 Uploaded_Files 라는 폴더를 하나 만들어주면 될 것입니다. ^^ 업로드된 파일들이 저장될 폴더로 말이지요. ^^

사실 업로드될 파일이 저장될 장소로 C 드라이브는 절대적으로 피하시는 것이 좋습니다. 안그러면 사람들이 파일을 많이 올리게되면 어느순간 C 드라이브는 공간이 부족하게 될 것이고, 시스템이 서버릴 수가 있으니까요. 루트 드라이브인 C 는 공간이 언제나 넉넉하게 남아있어야 한답니다.

그러한 폴더를 만들었다면, 이제 이 폴더에는 "쓰기" 권한을 부여해 주어야 합니다. 그래야 인터넷을 통해서 사람들이 파일을 이 폴더에 쓸 수가 있게(즉, 업로드 할 수 있게) 되는 것이지요. 반드시 "쓰기" 권한을 주어야지 안 그러면 Error 가 나게 됩니다. Write Permission Denied 와 같은 에러 메시지를 만나게 되지요.

이러한 작업을 완벽하게 하기 위해서, 탐색기와 인터넷 서비스 관리자에서 모두 Write 권한을 주도록 하겠습니다. 먼저 탐색기를 열어서 그 폴더를 찾아갑니다. 그리고는 그 폴더의 마우스 오른쪽 버튼을 눌러서 등록정보를 보도록 하세요.

그리고, 등록정보 창에서 [보안] 탭으로 이동합니다. 그리고, 목록중에 다음처럼 인터넷 게스트 계정에게 "모든권한"을 주세요. ^^ (실은 "수정" 권한 정도만 주어도 충분하기는 합니다만....)

그리고, 다음처럼 윈도우즈 시작버튼을 누르고, "실행"을 선택하시어서리...

다음처럼 실행창을 띄우시고, 다음 그림처럼 inetmgr을 실행하셔서 "인터넷 정보 서비스" 라는 IIS 관리툴을 실행하도록 합니다.

물론, 그냥 시작-> 프로그램-> 관리도구->인터넷 정보 서비스 의 단계로 이를 실행하실 수도 있습니다. ^^

고저, 우리 욘뵨에서는 마우스 클릭 두서너번은 클릭으로 텨주지도 않습네다. 고저 한 100번씩은 100단 콤보 스트레이트 연타로 눌러줘야 "아~~ 고거이 버튼에 때 좀 묻갔구나~" 합네다.. 

그리고, "기본 웹 사이트"에서리 여러분이 현재 게시판 파일을 테스트중인 가상 디렉토리를 찾아갑니다. 만일, 그냥 루트에서 테스트 중이신 분들. 즉, wwwroot 에서 테스트중이신 분들은 그냥 "기본 웹 사이트"를 선택하시면 됩니다. 저의 경우는 "Web"이라는 가상 디렉토리를 만들고 거기서 테스트중이기에 그 폴더로 이동해 보았습니다. (제 서버는 그 외에도 여러 다른 가상 디렉토리들이 많이 있어서 좀 지저분하게 보입니다)

그리고, 보시면 하위로 Uploaded_Files 라고 방금전에 만들어 놓은 폴더가 있는 것이 보이실 겁니다.

여기서도 마찬가지로 마우스 우측클릭을 하시고, [등록정보]로 갑니다. 그러면 다음 그림과 같은 윈도우가 뜨는데, 여기서 [쓰기(W)] 된 것에 체크를 해줍니다.

OK!! 이제 이러면 Uploaded_Files 라는 폴더에는 인터넷 사용자들이 파일을 쓸 수 있는 권한이 부여된 것이랍니다. 오직 이 폴더에만 파일을 올릴 수 있게 되지요..  ^^

그리고, 반드시 위의 윈도우에서 밑의 실행권한 부분을 "없음" 으로 해주시기 바랍니다. 아래 그림을 참고해서 말입니다. 만일, 이 세팅을 하지 않으면 얍삽한 사람들이 ASP 파일을 업로드하고 그를 실행할 수 있습니다. 일종의 크래킹이 가능하다는 것이지요. 반드시 이 부분은 "없음"으로 세팅해 주셔야 합니다. ^^ 반드시요... 그래야 업로드된 ASP 페이지가 실행되는 말도 안되는 현상을 막을 수 있고, ASP 페이지도 다운로드 되게 될 것입니다. ^^

그 다음에 해 주어야 할 것은 데이터베이스의 테이블 수정입니다. 우리는 기존의 게시판 테이블에 자료실 기능을 추가할 것이기에 업로드될 파일의 이름과 사이즈가 저장될 컬럼이 추가될 필요성이 있습니다. 테이블을 따로 가져가도 되겠지만, 우리는 기존의 MyBoard 테이블에 필요한 컬럼을 추가하는 형식으로 진행해 볼까 합니다.

파일명을 저장할 varchar(50)의 b_filename 이라는 컬럼과 int형의 b_filesize 라는 컬럼을 말이지요. 이를 위해서는 SQL 쿼리 애널라이저를 열어서 다음처럼 코드를 작성하고 실행하면 됩니다.

ALTER TABLE MyBoard ADD
   b_filename VARCHAR(50) NULL,
   b_filesize int Default 0

그림으로 확인해 보시자면 다음처럼 말이지요...

쿼리 애널라이저에 자신이 없으신 분들은 그냥 SQL 엔터프라이즈 매니저를 열고 테이블의 구조를 다음 그림처럼 수정해 주시면 됩니다. 파일 사이즈를 나타내는 b_filesize 컬럼에는 기본값으로 0 을 주시기 바랍니다. ^^ 이미 이러한 내용은 게시판의 첫번째 강좌에서 다 다룬 부분이니까 어려움이 없으리라 믿겠습니다.

자.. 그럼 이제 준비는 끝난 것일까요? 세팅은 이것으로 끝났다고 볼 수도 있습니다. 하지만, 여전히 이것이 전부는 아니죠? 그렇습니다. 이제는 Insert.asp 에서 실제적인 파일을 서버로 가져와서 저장하는 로직을 구성해주어야 합니다.

enctype을 "multipart/form-data"라고 지정하게 되면 이제 Request 객체는 사용할 수가 없게 됩니다. 고로, 기존의 Insert.asp 페이지에서 Request 객체로 name, mail, title, url 등등을 가져온 코드는 전면 수정이 되어져야 한답니다. 이제부터 바로 그것을 해 보아야 하겠죠? ^^

자.. 그럼 소스를 보시겠습니다. 파일을 서버로 업로드하여 저장하는 기능까지 완비(?)된 Insert.asp 페이지입니다. 소스를 보시고, 이전의 Insert.asp와 한번 비교해 보세요 ^^

<!--METADATA TYPE="typelib" NAME="ADODB Type Library"
FILE="C:\Program Files\Common Files\SYSTEM\ADO\msado15.dll" -->
<%
Option Explicit

Dim DirectoryPath
DirectoryPath = Server.MapPath("Uploaded_Files")'파일이 저장될 로컬폴더 경로

Dim abc, oFile
Set abc = Server.CreateObject("ABCUpload4.XForm")

Dim name, mail, title, url, memo, pwd, ipaddr
name = abc.item("name")
mail = abc.item("mail")
title = abc.item("title")
url = abc.item("url")
memo = abc.item("memo")
ipaddr = abc.item("ipaddr")
pwd = abc.item("pwd")

abc.AbsolutePath = True
Set oFile = abc("attachFile")(1)

Dim strFileName, FileSize, FileType, strFileWholePath

'실제적인 파일 업로드를 처리하는 부분
If oFile.FileExists Then
    strFileName = oFile.SafeFileName
    FileSize = oFile.Length
    FileType = oFile.FileType
    if oFile.Length > 4096000 then
        Response.Write "<script language=javascript>"
        Response.Write "alert(""4M 이상의 사이즈인 파일은 업로드하실 수 없습니다"");"
        Response.Write "history.back();"
        Response.Write "</script>"
        Response.end
    else
        strFileWholePath = GetUniqueName(strFileName, DirectoryPath)
        oFile.Save strFileWholePath
    End if
End if
'파일 업로드 처리 완료..

Dim strConnect
strConnect="Provider=SQLOLEDB;Data Source=(local);Initial Catalog= MyDatabase;userID=sa;password=;"
'만일, Access를 사용하신다면 위의 한줄을 다음처럼 바꾸시면 됩니다.
'strConnect="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Study\MyDataBase.mdb"

Dim adoRs
Set adoRs = Server.CreateObject("ADODB.RecordSet")
adoRs.Open "MyBoard", strConnect, adOpenStatic, adLockPessimistic, adCmdTable

with adoRs
    .AddNew
    .Fields("b_name") = name
    .Fields("b_email") = mail
    .Fields("b_title") = title
    .Fields("b_url") = url
    .Fields("b_pwd") = pwd
    .Fields("b_readnum") = 0
    .Fields("b_date") = now()
    .Fields("b_ipaddr") = ipaddr
    .Fields("b_filename") = strFileName
    .Fields("b_filesize") = FileSize
    .Fields("b_content") = memo

    .Update
    .Close
end with

Set adoRs = nothing
Response.Redirect "list.asp"



'유니크한 파일경로및 파일이름을 얻어내는 함수
Function GetUniqueName(byRef strFileName, DirectoryPath)

    Dim strName, strExt
    ' 확장자를 제외한 파일명을 얻는다.
    strName = Mid(strFileName, 1, InstrRev(strFileName, ".") - 1)
         strExt = '확장자를 얻는다
Mid(strFileName, InstrRev(strFileName, ".") + 1)

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

    Dim bExist : bExist = True
    '우선 같은이름의 파일이 존재한다고 가정
    Dim strFileWholePath : strFileWholePath = DirectoryPath & "\" & strName & "." & strExt
    '저장할 파일의 완전한 이름(완전한 물리적인 경로) 구성
    Dim countFileName : countFileName = 0
    '파일이 존재할 경우, 이름 뒤에 붙일 숫자를 세팅함.

    Do While bExist ' 우선 있다고 생각함.
        If (fso.FileExists(strFileWholePath)) Then ' 같은 이름의 파일이 있을 때
            countFileName = countFileName + 1 '파일명에 숫자를 붙인 새로운 파일 이름 생성
            strFileName = strName & "(" & countFileName & ")." & strExt
            strFileWholePath = DirectoryPath & "\" & strFileName
        Else
            bExist = False
        End If
    Loop
    GetUniqueName = strFileWholePath
End Function
%>

 

자.. 그럼 이제 기존의 소스에서 바뀐 부분을 중심으로 주~욱 살펴보도록 하겠습니다.

먼저, 소스의 상단에는 다음과 같이 파일이 업로드될 폴더의 물리적인 경로를 얻어와서 변수에 저장하는 다음 부분이 추가되어져 있습니다.

Dim DirectoryPath
DirectoryPath = Server.MapPath("Uploaded_Files") '파일이 저장될 로컬폴더 경로

Server.MapPath("Uploaded_Files") 라는 코드는 현재 ASP 페이지의 하위 디렉토리인 Uploaded_Files의 물리적인 경로를 찾아서 알려주는 역할을 합니다. 즉, 이 결과 리턴되는 값은 C:\Inetpub\wwwroot\Web\
Uploaded_Files 이 될 것입니다. 그렇죠?  ^^

그 다음 추가된 부분은 파일업로드 컴포넌트인 ABCUpload 객체의 인스턴스를 생성하는 부분입니다. 다음과 같은 부분이 바로 그것이지요. 저는 그 객체 인스턴스의 이름을 abc라고 주었습니다. 뭐.. 어떤 이름이어도 큰 문제는 없을 것이랍니다. ^^

Dim abc, oFile
Set abc = Server.CreateObject("ABCUpload4.XForm")

그리고, 폼에서 인코딩 타입이 바이너리로 지정되게 되면, 이 폼에서 전송된 값을 얻어오기 위해서는 더이상 Request 객체를 사용할 수가 없고, 대신 업로드 컴포넌트의 제공되는 메소드로 그값을 얻어와야 하기에, ABCUpload 컴포넌트의 경우는 그 메소드의 이름이 item 이기에 그 메소드를 사용해서 각각의 값들을 얻어오는 다음 코드를 보실 수가 있을 것이랍니다. ^^

Dim name, mail, title, url, memo, pwd, ipaddr
name = abc.item("name")
mail = abc.item("mail")
title = abc.item("title")
url = abc.item("url")
memo = abc.item("memo")
ipaddr = abc.item("ipaddr")
pwd = abc.item("pwd")

이전의 Request("..") 라고 되어져 있던 부분이 모두 abc.item("..") 이라고 바뀌어져 있는 것을 보실 수가 있을 겁니다.. ^^ 사실 abc.item("..") 이라는 부분은 abc("..") 이라고 간략하게 표기할 수도 있습니다만 확실하게 하기 위해서 그렇게 써 보았습니다. ^^

여기서 이상한 것은 전에는 없던 ipaddr = abc.item("ipaddr") 라는 부분인데요. 이 부분은 현재 이글을 작성한 클라이언트의 IP 주소를 남기기 위한 것이지요. 사실, 이 부분은 이전에는 다음과 같은 코드로써 존재했었습니다.

Request.ServerVariables("REMOTE_ADDR")

하지만, 이미 언급했다시피 폼에서 바이너리로 데이터를 넘기면 Request 객체는 사용할 수가 없게 됩니다. 해서, 이러한 코드도 사용할 수가 없게 되는 것이지요. 해서, 저는 글쓰는 폼에서 Hidden 컨트롤을 통해서 이 값을 미리 넘기도록 하였습니다.

즉, write.htm의 폼 부분을 다음과 같이 바꾸었다는 것입니다. 폼 소스 바로 밑에 한줄의 Hidden 컨트롤을 이렇게 추가했다는 것이지요.

<form method="POST" action="Insert.asp" name="myform" enctype="multipart/form-data">
<input type="hidden" name= "ipaddr"
       value="<%=Request.ServerVariables("REMOTE_ADDR")%>">

이렇게 폼에 히든으로 미리 그 값을 넘기니까 여기서는 단지 그 넘어온 값을 받아서 사용하도록 한 것이지요. 단, 원래 폼 페이지는 write.htm 이었다는 점을 기억하시기 바랍니다. 전에는 write.htm이었지만 이제는 위처럼 폼의 코드가 바뀌면서 ASP 코드를 사용하고 있으니 write.htm도 write.asp 로 확장자가 바뀌어야만 합니다. 그래야 ASP 코드가 제대로 동작해서 값이 제대로 넘어올 수 있게 된답니다. ^^

그렇게 처리하실 수 있을 것이라 믿구요. ^^. 계속 진행해 보겠습니다. ^^ 그 다음의 새로운 코드는

abc.AbsolutePath = True
Set oFile = abc("attachFile")(1)

입니다. 이는 폼에서 넘어온 파일을 oFile 이라는 이름의 변수에다가 저장하는 부분입니다. 이로써 바이너리 파일은 oFile 이라는 변수에 모두 저장이 된 것이지요...  ^^  사실상 abc("attachFile")(1) 라는 코드가 리턴해주는 객체는 ABCUpload 에서 지원하는 XField 라는 객체입니다. 해서 oFile 이라는 변수에 로드된 것은 실제로는 XField 의 모습을 하고 있지요. 그러므로 우리는 oFile 이라는 객체변수를 통해서 XField의 모든 프로퍼티와 메소드를 사용할 수가 있게 됩니다. 그 객체의 지원되는 프로퍼티와 메소드는 이전 강좌에서 강조드렸듯이, ABCUpload 의 Document를 참고하시기 바란답니다. ^^

그리고, 이제 이 파일을 먼저 서버에 저장하도록 합니다. 이제 이어지는 코드가 바로 그러한 처리를 하고 있지요.

'실제적인 파일 업로드를 처리하는 부분
If oFile.FileExists Then
    strFileName = oFile.SafeFileName
    FileSize = oFile.Length
    FileType = oFile.FileType
    if oFile.Length > 4096000 then
        Response.Write "<script language=javascript>"
        Response.Write "alert(""4M 이상의 사이즈인 파일은 업로드하실 수 없습니다"");"
        Response.Write "history.back();"
        Response.Write "</script>"
        Response.end
    else
        strFileWholePath = GetUniqueName(strFileName, DirectoryPath)
        oFile.Save strFileWholePath
    End if
End if
'파일 업로드 처리 완료..

파일이 먼저 서버에 저장된 다음에 데이터베이스에 그 정보를 저장하는 것이 말이 맞기에, 일단 먼저 파일을 저장하는데요. 이러한 작업은 파일이 모두 제대로 넘어왔다는 가정하에서 진행되어야 하기에 소스의 시작은 oFile.FileExists 라는 코드로 시작합니다. 이 프로퍼티는 제대로 객체변수에 파일이 올라와 있는지를 알려주는 프로퍼티 입니다. 이 값이 True라면 이제 믿고 파일을 서버에 저장해도 되는 것이지요.

그리고는 이제 파일명을 strFileName = oFile.SafeFileName 을 통해서 얻어내어 strFileName  라는 변수에 담도록 합니다. 그리고, 이어지는 코드로써 파일의 크기와 타입을 얻어내고 있습니다.

그리고, 만일 파일의 크기가 4M를 넘어선다면 서버의 부하를 줄이는 한 방편으로 업로드를 하지 못하도록 저는 정책적으로 정하고 있습니다. 또한, 제가 사용하고 있는 ABCUpload 컴포넌트는 5M이상(정확한 크기는 모르겠습니다만)이 되어지면 이상한 에러를 내면서 업로드가 Fail 하게 되더라구요. 현재 4.1 버전이상이 나와있는 것으로 압니다.. 어쩌면 그 버전에서는 fiX 되었는지도 모르겠네요 ^^

어쨋든 해서 4M 가 넘어서면 자바스크립트를 통해서 경고메시지를 보내고, 폼으로 돌려보내는 것이랍니다. 그리고, 만일 용량이 4M 이하여서 문제가 없다면 else 문을 통해서 이제 파일을 실제로 업로드 하는 것이지요.

oFile.Save strFileWholePath 라는 부분이 바로 실제로 파일을 저장하는 것을 나타내는 소스입니다만. 우리는 그 이전에 존재하는 단 한줄의 소스. 즉,

strFileWholePath = GetUniqueName(strFileName, DirectoryPath)

에 주목할 필요가 있습니다. ^^

도대체 이거이 무엇을 하는 거이일까? 이것은 바로..바로.. 백만년 묵은 거북이가 알을 까는 소리였던 것임다!!! 인걸까? 아닙니다. 이것은 바로 유니크한 파일이름을 얻어내는 부분의 코드입니다.

보도 듣도 못한 GetUniqueName 라는 함수는 페이지 하단에 따로이 만들어 두었습니다. 이것을 따로 함수로 만들어 둔 것은 소스의 가독성을 높이기 위함이며, 혹시 있을지 모르는 재사용성에 대비하기 위함이지요. 해서 저는 이렇듯, GetUniqueName라는 이름으로 현재 업로드하려는 파일과 같은 이름의 파일이 이미 Uploaded_Files 라는 폴더에 있는지 검사해서 있다면 그 이름을 약간 바꾸어 처리하는 로직의 함수를 만들어 둔 것입니다.

즉, 이미 Xfile.zip 이라는 파일이 존재하고 있는데, 우연히도 어떤 사람이 같은 이름의 파일을 저장하고자 할 경우에 이것이 덮어쓰여질 문제를 해결하기 위해서, 새로이 올라오는 Xfile.zip을 Xfiles(1).zip 이라고 저장하도록 하는 것이지요. 윈도우즈가 그렇게 하듯이 말입니다.

사실, 이 함수는 이미 인터넷에 공개되어져서 출처를 정확히 알 수 없는 상태로 떠돌고 있던 소스를 잡아다가 제가 양념만 조금 뿌려서 살짝 데친 것이기에... 무명씨인 그 원본자에게 감사하는 마음으로 사용하고 있습니다.

그러면, 이 함수를 한번 알아보겠습니다. 이 함수는 일단 두개의 인자를 요구합니다. 첫번째 인자는 사용자가 업로드 하고자 하는 파일의 파일명이어야 합니다. 두번째 인자는 파일이 업로드될 서버의 디렉토리경로명입니다. 이 두가지를 가지고서 함수는 뚝딱뚝딱 어떤 처리를 하고, 서버에 저장될 완전한 유니크한 이름의 파일전체 경로명을 리턴해 줄 것입니다.

다시 말해, 사용자가 업로드 하고자 하는 파일명이 XYZ.zip 이고, 서버에 저장될 업도르 파일 디렉토리가 C:\Inetpub\wwwroot\Web\Uploaded_Files 라고 했을 때,

서버에 아직 XYZ.zip이라는 이름의 파일이 존재하지 않고 있다면 이 함수는 리턴 경로로써 C:\Inetpub\wwwroot\Web\Uploaded_Files\XYZ.zip 을 넘겨줄 것이고,

만일, 서버에 이미 XYZ.zip 이라는 이름의 파일이 존재하고 있다면 이 함수는 리턴 경로로써 C:\Inetpub\wwwroot\Web\Uploaded_Files\XYZ(1).zip 을 넘겨줄 것이라는 이야기입니다.

그리고, 이미 XYZ.zip과 XYZ(1).zip이 모두 존재하고 있다면 이 함수는 리턴경로로써 C:\Inetpub\wwwroot\Web\Uploaded_Files\XYZ(2).zip 을 넘겨줄 것이라는 이야기입니다.

어떻게 이 함수로 그런 일을 처리하는지 함수를 한번 살펴봅시다.

Function GetUniqueName(byRef strFileName, DirectoryPath)

    Dim strName, strExt
    strName = Mid(strFileName, 1, InstrRev(strFileName, ".") - 1) ' 확장자를 제외한 파일명을 얻는다.
    strExt = Mid(strFileName, InstrRev(strFileName, ".") + 1) '확장자를 얻는다

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

    Dim bExist : bExist = True
    '우선 같은이름의 파일이 존재한다고 가정
    Dim strFileWholePath : strFileWholePath = DirectoryPath & "\" & strName & "." & strExt
    '저장할 파일의 완전한 이름(완전한 물리적인 경로) 구성
    Dim countFileName : countFileName = 0
    '파일이 존재할 경우, 이름 뒤에 붙일 숫자를 세팅함.
    Do While bExist ' 우선 있다고 생각함.
        If (fso.FileExists(strFileWholePath)) Then ' 같은 이름의 파일이 있을 때
            countFileName = countFileName + 1 '파일명에 숫자를 붙인 새로운 파일 이름 생성
            strFileName = strName & "(" & countFileName & ")." & strExt
            strFileWholePath = DirectoryPath & "\" & strFileName
        Else
            bExist = False
        End If
    Loop
    GetUniqueName = strFileWholePath
End Function

먼저, 함수는 첫번째 인자로 넘어온 파일명에서 파일이름과 확장자를 각각 뽑아내어서 변수에 저장하도록 하고 있습니다.

그리고, FSO 개체를 생성하고(단지, FileExists 라는 유용한 함수를 사용하기 위해서), strFileWholePath  라는 경로에 두번째 인자와 첫번째 인자를 합쳐서 일단 전체경로를 가볍게 만들어 봅니다.

해서, FSO의 FileExists 메소드를 통해서 이 전체경로와 일치하는 파일이 이미 있는지 살펴보아서 만일 이러한 경로의 파일이 존재하지 않는다면 그대로 이를 사용하면 될 것이고, 만일 같은 이름의 파일이 이미 존재한다면 파일명뒤에다가 루프를 돌면서 (1), (2), (3)... 과 같은 식으로 넘버를 추가하는 것이지요. 같은 이름의 파일이 존재하지 않는 번호가 나올 때까지 말입니다. 어렵지는 않은 내용이지요?

그렇습니다. 모든 과정이 다 끝난 다음에는 GetUniqueName = strFileWholePath 를 통해서 그 만들어진 경로를 리턴하도록 하고 있습니다. ^^ 이제... 이 경로 그대로 파일을 저장하면 되는 것이지요.

해서 우리의 소스에서는 이 함수를 이용하여

strFileWholePath = GetUniqueName(strFileName, DirectoryPath)
oFile.Save strFileWholePath

라는 두줄로 이 모든 것을 해결한 것이랍니다. ^^ 쉽죠?

이제 파일은 서버에 저장되었으니, 데이터베이스에 이 내용을 또한 저장하는 것이 남아있네요. 이 부분은 어려울 것이 없는 부분이지요. 단지, 기존의 소스에다가 파일명과 파일사이즈를 저장하는 부분만을 추가하면 됩니다. 단 두줄이지요.. 이 부분에는 어려움이 없을 것이라 믿겠습니다.

모든 것이 되었으니 한번 파일을 업로드 해보시기 바랍니다. 같은 이름의 파일을 중복해서 업로드 해보시기도 하시구요. 저의 경우는 "감수커멘트.txt" 라는 파일을 두번 연속으로 올려보았습니다. 그랬더니 다음처럼 맘에 드는 결과를 얻게되네요...  ^^

이로써 파일을 서버에 저장하는 부분은 간단하게 해결이 된 것 같네요..  ^^ 이제 남은 부분은 이 내용을 디스플레이해 주는 부분이 되겠습니다. 하지만, 이 내용은 다음 강좌에서 마무리하도록 하려 합니다.  강좌가 너무 길면 여러분도 조금은 지루해지니까요..  ^^

다음 시간에 다운로드하는 것과 디스플레이부분을 하겠습니다만.. 이 부분은 그리 어려운 부분이 아니기에 여러분이 스스로도 하실 수 있을 것 같다는 생각이 드네요.. 특히 제 책을 통해서 이미 자료실을 만들어 보신 분들은 디스플레이 부분은 책과 거의 같으니 어려움이 없으실 것입니다.

강좌를 마무리하기 전에 말씀을 드리면 이번 강좌에서 주의깊게 기억하셔야 할 부분은 파일 업로드 컴포넌트를 다루는 부분이 아닌, GetUniqueName 라는 함수입니다. 파일 업로드 컴포넌트야 다른 제품을 쓰게 되면 그에 따라 소스가 또한 바뀔 수도 있지만, GetUniqueName 라는 함수의 로직은 앞으로도 상당히 유용하게 쓰일 수 있게 될 것입니다.

.NET으로 들어서면 파일 업로드는 단 2-3 줄로 간단히 업로드 컴포넌트없이 구현할 수 있게 되지만, 그 때에도 필요한 것은 유니크한 파일 이름을 얻어낼 수 있게 해주는 GetUniqueName 와 같은 함수입니다. 그러니, 그 함수를 꼭 이해하시고 머리속에 잘 보관하시기 바란답니다.

실제로 우리가 공부하고, 기억해야 하는 것은 구현하는 테크닉도 물론이겠지만, 그보다는 알고리즘과 로직이라는 것을 기억하세요.. 두고두고 도움이 되는 것은 바로 그러한 눈에 직접적으로 보이지 않는 부분이랍니다.

좋은 하루 되세요...  ^^

휘유~~ 간만에 강좌를 쓰려니 아주 약간 힘이 부치는 것을 느끼네요...   남는 힘은 빈대떡이나 녹두전을 부치는 데 써볼까 합니다. -_-;

유치하다구요? 음... 이럴수가.. 정말로 난 아저씨가 된 것일까요?  T.T


authored by

  공포의빽구두
  2009-06-10(16:22)
캐릭 이미지
안녕하세요. 강좌 잘보고 있습니다.^^ 질문한가지만하려구요.
강좌에서 input type="file" name="attachFile로 해서 파일을 업로드 하고 있는데요
그렇게 되면 여러개를 올리려고 할때 input... 이것을 여러번 써줘야 하자나요.
그리고 써준만큼 올릴수 있다는 제한도 있고요.
효과적으로 여러 파일을 올릴수 있는 방법은 어떤것이 있는지 궁금합니다..


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})