반응형

복잡한 문제를 해결해야했다.

현상황은 다음과 같다.

두대의 iis가 있다. 한쪽은 WebServer이고 다른한쪽은 ImageServer이다.

골때리는 점은 Web에서 Img로 파일을 업로드할때 파일공유방식으로 전송하고 있다는 점이다.

Web이 \\ImgServerPath 와같이 공유폴더로 접근해서 파일을 업로드하고있다.


문제는 Web서버를 한대 증설하면서 공유폴더방식으로 접근이 안된다는 점이다. GUI단에서는 작업이 되지만

IIS수준에서는 붙지 않아서 파일업로드를 못하고 있다. 이를 해결하기 위해 잔머리를 굴렸다.


그러다가 파일을 Base64String으로 변환해서 POST전송하면 되겠다는 아이디어를 떠올렸다.

어차피 ImgServer도 IIS이므로 동일한 환경으로 세팅이 가능하기에 Img에도 asp.net을 구축할 수 있다.


구현단계에서 발견한 추가문제가 있었다.

5MB이상용량의 파일을 전송할 수가 없었다. 10M이상의 파일을 업로드 하지 못하기 때문에 이를 해결하기 위해 머리를 또 굴렸다.

Base64로 변환된 String은 길이기 길기때문에 잘릴 수도 있겠다 싶었다.

그래서 Base64를 압축해서 전송하면되겠다는 두번째 아이디어를 떠올렸다. 이문제를 며칠 동안 찾아 해맸다.


그리고 해결했다.


절차를 다시 정리하면 다음과 같다.

    1. 파일을 MemoryStream으로 변환(MemoryStream생성과정에 GZipStream을 통해 압축)

    2. MemoryStream을 Base64로 변환

    3. Base64문자열을 POST로 전송

    4. POST로 받은 문자열을 파일로 변환


※ using System.IO.Compression; //GZipStream을 사용하기 위한 선언


A)파일전송


           HttpFileCollection addFile = HttpContext.Current.Request.Files;


           string url = "http://ImgServer.url/Data_send.aspx";

           string sFiles_Name = "";


           string postParm = "";

           string tmpParm = "";

           for (int i = 0; i < addFile.Count; i++)

           {

               HttpPostedFile postedFile = addFile[i];

               if (postedFile.ContentLength > 0)

               {

                   sFiles_Name = postedFile.FileName;

                   Stream sm = postedFile.InputStream;

                   BinaryReader br = new BinaryReader(sm);

                   byte[] byt = br.ReadBytes((Int32)sm.Length);

                   sm.Dispose();

                   br.Close();


                   string base64 = "";

                   

                   using(MemoryStream ms = new MemoryStream())

                   {

                       using (BufferedStream bs = new BufferedStream(new GZipStream(ms, CompressionMode.Compress), (64 * 1024)))

                       {

                           bs.Write(byt, 0, byt.Length);

                       }

                       base64 = Convert.ToBase64String(ms.ToArray());

                   }

                   tmpParm += base64 + '#'; //#은 파일구분자(여러개의 파일을 추가했을경우)

               }

           //POST 파라미터 

           postParm = string.Format("save_data={0}", tmpParm);


           try

           {

               //POST전송

               byte[] datatCategory = UTF8Encoding.UTF8.GetBytes(postParm);

               HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);

               req.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";

               req.Method = "POST";

               req.ContentLength = datatCategory.Length;

               Stream requestStream = req.GetRequestStream();

               requestStream.Write(datatCategory, 0, datatCategory.Length);

               requestStream.Close();

               HttpWebResponse httpWebResponse = (HttpWebResponse)req.GetResponse();

               StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("UTF-8"));

               string rtn = streamReader.ReadToEnd();

               streamReader.Close();

               httpWebResponse.Close();

           }

           catch (Exception ex)

           {

               //throw ex;

           }


B)파일수신(string url = "http://ImgServer.url/Data_send.aspx";에 해당)


           HttpFileCollection addFile = HttpContext.Current.Request.Files;


           string save_data = "";

            

           try

           {

               save_data = Request.Form["save_data"].Replace(" ", "+");    //Replace해줘야함 "+"문자가 " "으로 변환되서 넘어옴

           }

           catch (Exception ex)

           {

               save_data = "";

               Response.Write(ex.Message);

               return;

           }

           

           if (save_data != null && save_data != "")

           {

               string[] aryFiles = save_data.Split("#");

               string svrPath = Server.MapPath(".").Replace("\\", "/");

               for (int i = 0; i < aryFiles.Length - 1; i++)

               {

                   byte[] bytData = Convert.FromBase64String(aryFiles[i]);

                       try

                       {

                           DirectoryInfo di = new DirectoryInfo(svrPath + "/folder");

                           if (!di.Exists)

                           {

                               di.Create();

                           }


                           using(MemoryStream ms = new MemoryStream(bytData))

                           {

                               using(MemoryStream dms = new MemoryStream())

                               {

                                   using(BufferedStream bs = new BufferedStream(new GZipStream(ms, CompressionMode.Decompress),(64*1024)))

                                   {

                                       bs.CopyTo(dms);

                                   }        

                                   using (FileStream fs = new FileStream(svrPath + "/folder/save_filename.file", FileMode.Create, System.IO.FileAccess.Write))

                                   {

                                       byte[] bt = dms.ToArray();

                                       dms.Read(bt, 0, (int)dms.Length);

                                       fs.Write(bt, 0, bt.Length);

                                       fs.Flush();

                                   }

                               }

                           }

                       }

                       catch(Exception ex)

                       {

                           Response.Write("false : " + ex.Message);

                           return;

                       }

               }

               Response.Write("true");

           }



※ 참고 : http://toreaurstad.blogspot.com/2014/01/compressing-byte-array-in-c-with.html

+ Recent posts