본문 바로가기

C#/근웹 연대기

c#으로 근본 없는 웹서버 개발기 6 : minetype

⚠WARNING
ASP.NET에 대한 포스팅이 아닙니다
나가실 문은 오른쪽 하단입니다

 

 

minetype이 image/png인 스샷

HTTP를 이용하여 파일을 전송하고자 할 땐 content-type이라는 것을 명명하여 

각각 파일 확장자에 맞는 minetype을 표기를 하여 보내줘야 한다.
예를 들어 text를 보냈는데, minetype이 image일 경우는 브라우저 창에는 아무것도 표기되지 않는다.

어차피 파일마다 확장자가 있기에 무슨 필요가 있느냐고 질문을 할지 모르겠지만, 파일에 확장자를 쓰지 않는 경우도 있다. 그런 경우는 minetype에 전적으로 의지 할 수밖에 없다.

 

다음 내용은 모질라 사이트에서 minetype으로 검색한 내용을 긁어와 csv파일 형태로 정리한 형태다.

.aac,AAC 오디오 파일,audio/aac
.abw,AbiWord 문서,application/x-abiword
.arc,아카이브 문서 (인코딩된 다중 파일),application/octet-stream
.avi,AVI: Audio Video Interleave,video/x-msvideo
.azw,아마존 킨들 전자책 포맷,application/vnd.amazon.ebook
.bin,모든 종류의 이진 데이터,application/octet-stream
.bz,BZip 아카이브,application/x-bzip
.bz2,BZip2 아카이브,application/x-bzip2
.csh,C-Shell 스크립트,application/x-csh
.css,Cascading Style Sheets (CSS),text/css
.csv,Comma-separated values (CSV),text/csv
.doc,Microsoft Word,application/msword
.epub,Electronic publication (EPUB),application/epub+zip
.gif,Graphics Interchange Format (GIF),image/gif
.htm,HyperText Markup Language (HTML),text/html
.html,HyperText Markup Language (HTML),text/html
.ico,Icon 포맷,image/x-icon
.ics,iCalendar 포맷,text/calendar
.jar,Java 아카이브 (JAR),application/java-archive
.jpeg,JPEG 이미지,image/jpeg
.jpg,JPEG 이미지,image/jpeg
.js,JavaScript (ECMAScript),application/js
.json,JSON 포맷,application/json
.mid,Musical Instrument Digital Interface (MIDI),audio/midi
.midi,Musical Instrument Digital Interface (MIDI),audio/midi
.mpeg,MPEG 비디오,video/mpeg
.mpkg,Apple Installer Package,application/vnd.apple.installer+xml
.odp,OpenDocuemnt 프리젠테이션 문서,application/vnd.oasis.opendocument.presentation
.ods,OpenDocuemnt 스프레드시트 문서,application/vnd.oasis.opendocument.spreadsheet
.odt,OpenDocument 텍스트 문서,application/vnd.oasis.opendocument.text
.oga,OGG 오디오,audio/ogg
.ogv,OGG 비디오,video/ogg
.ogx,OGG,application/ogg
.pdf,Adobe Portable Document Format (PDF),application/pdf
.ppt,Microsoft PowerPoint,application/vnd.ms-powerpoint
.rar,RAR 아카이브,application/x-rar-compressed
.rtf,Rich Text Format (RTF),application/rtf
.sh,Bourne 쉘 스크립트,application/x-sh
.svg,Scalable Vector Graphics (SVG),image/svg+xml
.swf,Small web format (SWF) 혹은 Adobe Flash document,application/x-shockwave-flash
.tar,Tape Archive (TAR),application/x-tar
.tif,Tagged Image File Format (TIFF),image/tiff
.tiff,Tagged Image File Format (TIFF),image/tiff
.ttf,TrueType Font,application/x-font-ttf
.vsd,Microsft Visio,application/vnd.visio
.wav,Waveform Audio Format,audio/x-wav
.weba,WEBM 오디오,audio/webm
.webm,WEBM 비디오,video/webm
.webp,WEBP 이미지,image/webp
.woff,Web Open Font Format (WOFF),application/x-font-woff
.xhtml,XHTML,application/xhtml+xml
.xls,Microsoft Excel,application/vnd.ms-excel
.xml,XML,application/xml
.xul,XUL,application/vnd.mozilla.xul+xml
.zip,ZIP archive,application/zip
.3gp,3GPP 오디오/비디오 컨테이너,video/3gpp
.3g2,3GPP2 오디오/비디오 컨테이너,video/3gpp2
.7z,7-zip 아카이브,application/x-7z-compressed
?,another,application/octet-stream
 

(확장자, 설명, minetype 순이다)

csv의 파일에 위 내용처럼 하이라이트를 주고자 할 경우 vscode의 확장 탭에서 csv라고 검색하면 가장 위에 위치하는 Rainbow csv라는 녀석을 설치하면 된다. 

그렇다

先手必勝(선수필승)이라 하여 밑에 있는 것이 설령 더 좋은 기능과 서비스를 갖추고 있다한들 사람들은 대부분 위쪽의 것을 선택할 것이다.

그렇다

새 🌱이 자라나기에는 너무 척박한 환경이다.

 

참고로 가장 아래에 있는 "?"는 본인이 임으로 적은 것으로 application/octet-stream은 일치하는 것이 없을 때 기본으로 사용되는 minetype이라고 한다. 그리고 그냥 텍스트를 보내고자 할 경우는 text/plane으로 하면 무난한다.

 

다음 내용은 저장되어 있는 csv의 파일에서 내용을 불러오는 소스이다.

public static readonly string sPath = Environment.CurrentDirectory;
public static readonly Dictionary<string, string> mineTypeDic = loadMineType();
static Dictionary<string, string> loadMineType(){
    var dic  = new Dictionary<string,string>();

    using(var reader = new StreamReader(File.OpenRead(sPath+"/minetype.csv"))){
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var values = line.Split(',');
            dic.Add(values[0].Trim(), values[2].Trim());
            Console.WriteLine(line);
        }
    }
    return dic;
}

해당 csv파일은 어차피 프로그램을 실행하면 한 번만 불러오는 것으로 static constructor를 이용하여도 되지만, 나중에 복사 붙여 넣기를 활용한 재활용성을 위하여 저런 식으로 함수의 리턴 값을 불러오는 방법을 택하였다. 주의해야 할 점은 저 함수는 프로그램을 실행하자마자 호출되는 것이 아니고 클래스의  멤버나 메서드를 사용할 때 실행된다.

 

그리고 위의 코드를 사용하는 코드를 사용하는 코드.

        Socket client = server.Accept();
        try
        {
            var dic = request(client);

            if (dic.ContainsKey("err"))
            {
                resForbadrequest(client, dic["err"]);
                client.Close();
                continue;
            }

            if (dic["url"] == "/")
            {
                dic["url"] = "/index.html";
            }
               
            response(client, dic);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        finally
        {
            client.Close();
        }

전편의 코드에서 약간 수정되었다.

 

그리고 위의 코드에서 사용당하는 코드

static void response(Socket client, Dictionary<string,string> dic)
{
    string fpath = Util.sPath + "/public" + dic["url"];
    var info = new FileInfo(fpath);
    var ext = Path.GetExtension(info.Name);
    if(Util.mineTypeDic.ContainsKey(ext) == false) ext = "?";
 
    StringBuilder sb = new StringBuilder(100);

    sb.AppendLine($"HTTP/1.1 200 ok");
    sb.AppendLine("Accept-Ranges: none");
    sb.AppendLine("Cache-Control: public, max-age=0");
    sb.AppendLine("Last-Modified: " + Util.utcEng(info.LastWriteTime));
    sb.AppendLine("Etag: " + DateTime.UtcNow.Ticks.ToString("x2"));
    sb.AppendLine("Date: " + Util.uTime);
    sb.AppendLine("Content-type: " + Util.mineTypeDic[ext]);
    sb.AppendLine("Server: test server");
    sb.AppendLine("Content-Length: " + info.Length);
    sb.AppendLine("Connection: close");
    sb.AppendLine();
       
    client.Send(Encoding.UTF8.GetBytes(sb.ToString()));
    client.Send(File.ReadAllBytes(info.FullName));
}

설명:  요청 파일의 확장자를 기준으로 일치하는 minetype이 적용된다.

 

마무리로 과거에 작성하였던 소스를 public폴더에 넣고 해당 url에서 작동하는 모습을 확인할 수 있다.

html파일 내용인 src부분의 myReacts.js가 전송되었다.

つづく