반응형

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

현상황은 다음과 같다.

두대의 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

반응형

byte[] data = null;

using (var br = new BinaryReader(uploadfile.PostedFile.InputStream))

{

data = br.ReadBytes(uploadfile.PostedFile.ContentLength);

}

#####################################################


byte[] data를 MemoryStream등으로 변환해서 쓸 수 있다ㅏ.

반응형
public static void Main()
{
    string data = "%B3%F3%C7%F9";
    byte[] bData = new byte[data.Length / 3];
    for (int i = 0; i < data.Length; i += 3)
    {
        int pos = i / 3;            
        bData[pos] = Convert.ToByte(data.Substring(i + 1, 2), 16);
    }
    data = System.Text.Encoding.GetEncoding("euc-kr").GetString(bData);
    Console.WriteLine(data);
}


출처 : https://stackoverflow.com/questions/47193248/decoding-code-string-to-utf8-and-string


파라미터를 EUC-KR로 넘겨서 받아오는 과정에 디코딩이 제대로 안되는 바람에 애를 먹었다.

한글 인코딩 문자를 변환하는 방법을 출처에서 찾았다.



//추가 방법

public static void Main()
{
    byte[] buffer = Request.BinaryRead(Request.TotalBytes);
    string url = System.Web.BinaryRead(Request.TotalBytes);
}

출처 : http://blog.naver.com/PostView.nhn?blogId=doksajokyo&logNo=220835329973&parentCategoryNo=6&categoryNo=&viewDate=&isShowPopularPosts=true&from=search

반응형

굉장히 간단한 내용이다.

AJAX로 사용하는 요즘은 거의 사용할 일이 없는 태크닉인데

asp.net 2.0으로 구축된 사이트를 유지보수하다 보니 발생하는 귀찮음 때문에 찾아보다가 주저리 주저리 써본다.


Page.aspx에 


<asp:Label ID="lbl01" runat="server"></asp:Label>

<asp:Label ID="lbl02" runat="server"></asp:Label>

<asp:Label ID="lbl03" runat="server"></asp:Label>

<asp:Label ID="lbl04" runat="server"></asp:Label>

<asp:Label ID="lbl05" runat="server"></asp:Label>


와 같이 Label컨트롤을 순차적으로 생성 돼있다.

이 Label들에 값들을 일일이 코딩해주려니 귀찮고  for문등을 이용해서 자동으로 값을 넣고 싶은데 방법을 잘모르겠고...


여튼 해결 방법은 다음과 같다.

((Label)Page.FindControl(id)).Text = _txt;

굉장히 단순하다.

이를 응용해서 for문으로 값을 넣는다면

string[] _values = {"1","2","3","4","5"};

의 값을 자동으로 넣는다고 가정해보자.

for(int i = 0; i < 5; i++)

{

((Label)Page.FindControl("lbl0" + (i + 1).toString() )).Text = _values[i];

}

이런식으로 처리하면 매우 간단하다. 

여튼 핵심은 Page.FindControl("ID")가 돼겠다.



반응형

Response.Expires = 0;

Response.Cache.SetNoStore();

Response.AppendHeader("Pragma", "no-cache");


OpenFlashChart를 asp.net2.0에 참조 하였더니 ie에서 문제가 발생했다.

Chart를 재생성할때마다 서버에 접근해야 하는데 캐쉬문제 때문인지 서버에 접근하지 않고 최초에 생성한 Chart가 반복되는 현상이 발생했다.

(크롬에서는 발생하지 않는 문제) 이를 해결하기 위해 해당 페이지에 상기의 코드를 추가 한다.


반응형
1. http://www.uploadify.com/ 에서 jQuery플러그인을 받는다.(asp.net)

 [Uploadify.htm]


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>파일업로드 : jQuery + Uploadify + ASP.NET</title>

    <link href="uploadify.css" rel="stylesheet" type="text/css" />

    <script src="../../js/jquery-1.3.2-vsdoc2.js" type="text/javascript"></script>

    <script src="jquery.uploadify.v2.1.0.js" type="text/javascript"></script>

    <script src="swfobject.js" type="text/javascript"></script>

    <script type="text/javascript">

        $(document).ready(function () {

        // Uploadify 파일 업로드 컨트롤 : Flash가 설치가 되어있어야 함

            $('#fileInput').uploadify({

                'uploader' : 'uploadify.swf'// Uploadify 컨트롤 지정

                'script' : 'Uploadify.ashx'// 서버측 스크립트, ASP.NET, ASP, PHP, JSP

                'cancelImg''cancel.png'// 취소 이미지

                'auto' : false// true면 파일선택시 바로 자동으로 업로드됨

                'folder''/Uploads'// 업로드할 폴더 : 가상디렉터리 + 업로드폴더

                // 업로드 완료시 처리 :

                //      주요 속성은 http://www.uploadify.com/documentation/ 참고

                'onComplete'function (event, queueID, fileObj, response, data) {

                    $('#lblFile').append('<a href=/WebJQuery' + fileObj.filePath + '>'

                    + fileObj.name + '</a><br>');

                }

            });

            // 버튼 클릭시 업로드

            $('#btn').click(function () { $('#fileInput').uploadifyUpload(); });

        });

    </script>

</head>

<body>

    <input id="fileInput" name="fileInput" type="file" />

    <input type="button" id="btn" value="업로드" />

    <div id="lblFile"></div>

</body>

</html>

 




-------------------------------------------------------------------------------------


 

[Uploadify.ashx]


<%@ WebHandler Language="C#" Class="Uploadify" %>

 

using System;

using System.Web;

 

public class Uploadify : IHttpHandler {

   

    public void ProcessRequest (HttpContext context) {

        // Filedata로 넘겨온 파일 값 받기

        HttpPostedFile file = context.Request.Files["Filedata"];

        // 저장할 폴더

        string targetDirectory = System.IO.Path.Combine(

        context.Request.PhysicalApplicationPath,

        context.Request["folder"].Replace("/"""));

        // 저장할 폴더 + 파일명

        string targetFilePath = System.IO.Path.Combine(

            targetDirectory, file.FileName);

        // 파일 저장(업로드)

        file.SaveAs(targetFilePath);

 

        context.Response.Write("RedPlus");

    }

 

    public bool IsReusable {

        get {

            return false;

        }

    }

 

}
[출처] : http://holland14.tistory.com/538
 

2. 파일을 업로드할경우 변수를 넘겨야하는 경우가 있다.
1)의 소스대로 하면 변수는 $(document).ready()상에 지정해야하는데 데이터를 미리 받아오기전에는
변수를 넘기기 힘들다. 
그래서 

            // 버튼 클릭시 업로드

            $('#btn').click(function () { $('#fileInput').uploadifyUpload(); });



이부분에 변수를 넘길 수 있는 처리를 추가해야한다.
var _obj = $('#fileInput');

_obj.uploadifySettings('scriptData', { 'code1': 'data01', 'code2': 'data02' });

_obj.uploadifyUpload();

이부분을 처리해주면 업로드 할때 변수(code1,code2)의 값을 전달할 수 있다.

반응형
                WebClient request = new WebClient();
                request.Credentials = new NetworkCredential(ftp_uid, ftp_upw);
                byte[] newFileData = request.DownloadData(ftp_url  + "/" + filecode);

                Response.ClearHeaders();
                Response.AddHeader("Content-Type", "application/vnd.ms-excel");
                Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", filename));
                Response.ContentType = "multipart/form-data";
                Response.BinaryWrite(newFileData);
                Response.End();

 원격FTP에 있는 데이터를 byte[]로 읽어서 저장하는 방법이다.
반응형
1.먼저 [using System.Collections.Specialized;]이 선언돼있어야 한다.
2. QueryString을 처리할 함수를 만든다.
        public NameValueCollection getQueryStringPrms(string url)
        {
            string keyValue = string.Empty;
            NameValueCollection collection = new NameValueCollection();
            string[] querystring = url.Split('&');
            if (querystring != null && querystring.Count() > 0)
            {
                for (int i = 0; i < querystring.Count(); i++)
                {
                    string[] pair = querystring[i].Split('=');
                    collection.Add(pair[0].Trim('?'), pair[1]);
                }
            }
            return collection;
        } 
3. [WebMethod]에서 getQueryStringPrms을 호출한다.
        NameValueCollection collection = comm.getQueryStringPrms(HttpContext.Current.Request.UrlReferrer.Query);
        
         string temp = HttpContext.Current.Server.UrlDecode(collection["code"]);
 
반응형
1.[WebMethod] - > [WebMethod(EnableSession=true)]
2. HttpContext.Current.Session["sessionID"]

 
반응형
마스터페이지로 사이트를 구성하다보면 TextBox에 엔터키를 입력했을 경우 엉뚱한 동작이 발생하는 경우가 있다.
내경우에는 마스터페이지에 올려놓은 로그아웃버튼이 동작을 한다.

해결방법은 두가지가 있다.

1.자바스크립트로  if(event.keyCode == 13) return false; 를 심어주는 방법이다.
내경우엔 TextBox1.Attributes["onKeyPress"] = "if(event.keyCode == 13) return false;";라고 추가했다.

그러나 1의 방법은 한계가 있다. 모든컨트롤을 일일이 등록해야하고 html컨트롤은 별도로 추가해야하는 불편함이 있다.

2. 다른방법은 마스터페이지에 defaultbutton속성을 이용하는 것이다.
먼저  아래와 같이 서버컨트롤 버튼을 추가한다. 물론 <div>로 감싸서 화면에는 보이지 않도록 한다.
<div style="display:none"><asp:Button ID="btnNull" runat="server" /></div> 
그리고 <form에  defaultbutton에 추가한 서버컨트롤 ID를 작성한다.
<form id="form1" defaultbutton="btnNull">

 
참고로 엔터키 입력할때마다 페이지리프래쉬가 일어나는 현상을 막기 위해서
마스터 페이지 최초로딩시 btnNull버턴의 onclick이벤트에 엔터키를 막는 1의 코드를 등록했다.
btnNull.Attributes["onclick"] = "return EnterKeyBlock();";
[EnterKeyBlock()]가 자바스크립트 함수로 1).의 자바스크립트를 기록해둔 것이다.

+ Recent posts