Skeleton Screen ?

최근 웹페이지를 들어가면 로딩중에 저런 화면을 많이 본적이 있을 것이다.

유투브, 페이스북에서도 로딩중에 많이 사용 하는 화면인데 일명 "Skeleton Screen" 이라고 부른다.

 

CSS linear-gradient를 통한 Skeleton Screen

linear-gradient() CSS 함수는 두 개 이상의 색이 직선을 따라 점진적으로 변화하는 이미지를 생성한다. 함수의 결과는 <image>의 특별한 종류인 <gradient>자료형이다.

<gradient> <image>의 한 종류로서 <image>를 사용하는 곳에만 적용할 수 있다. 따라서 linear-gradient()를 background-color  <color> 자료형을 받는 속성에는 사용할 수 없다.

ex1) 사용법 linear-gradient([driection], #color1, #color2) (2개 이상의 색상은필수이다.) (driection 에는 top, left, right deg 등 다양한 인자를 사용 가능하다.)

.example-element {
  width:300;
  height:400;
  background: linear-gradient(0, blue, black);
}

 

정 중앙을 기준으로 두개의 색이 그라데이션됨

 

- direction 부분에 degree를 줘서 각도만큼 비틀수도 있다. ingredient는 축을기준으로 무수한 선을 긋는 개념이기때문에, 각도를 준다면 다음처럼 축을 기준으로 휘어진 선이 휘게된다.

 

ex2) 축을 45도만큼 휘게 사용

.example-element {
  width:300;
  height:400;
  background: linear-gradient(45deg, blue, black);
}

정사각형이 아니므로 정확한 대각선은 아닐수도..

 

CSS linear-gradient 을 활용하여 게시글을 표현해보자.

ex3) linear-gradient 를 이용해서 글 한줄 한줄을 표현해보자.

.example-element {
  width:300;
  height:400;

  background-image:
    linear-gradient(lightgrey 15px, transparent 0),
    linear-gradient(lightgrey 15px, transparent 0),
    linear-gradient(lightgrey 15px, transparent 0);
}

 

- 오잉? 근데 3분명히 3줄을 추가했는데 한줄만 나온다? 왜그럴까??? -> 현재 3줄의 좌표가 겹쳐있기때문이다.

background-position: [x 위치, y 위치] 를 추가해서 각각 ingredient의 좌표를 달리해보자.

 

.example-element {
  width:300;
  height:400;

  background-image:
    linear-gradient(lightgrey 15px, transparent 0),
    linear-gradient(lightgrey 15px, transparent 0),
    linear-gradient(lightgrey 15px, transparent 0);
  
  background-position:
  /* 좌측에서 5px만큼 y축으로 5px(선굵기-간격[15px-20px])씩 띄움 */
    5px 10px,
    5px 30px,
    5px 50px;
  background-size:
  /* gradient 기준으로 width height 만한 사각형을 만든다고 생각 하자*/
    100px 100px,
    150px 100px, 
    150px 100px;  
  background-repeat: repeat-y;
}

- 또한 나는 background-size 라는 속성을 주었는데, 사용법은 width 값과 height 값을주면된다. 이 값은 gradient 자체의 width와 height가 아닌 gradient 부터 시작하는 사각형을 준다고 생각하면 된다. 이를 명시하는 이유는 background-repeat: repeat-y; 라는 속성을 주면 y축으로 gradient를 계속 반복할 수있다.

 

width heigth 값은 gradient 선의 속성이 아님을 유의하자

 

 

- 이제 제법 그럴싸하지않은가?? 뭔가좀 허전하니 마지막으로, 애니메이션만 추가해보자.

See the Pen example by EdgarHan (@EdgarHan) on CodePen.

 

 

 

 

 

 

출처

https://developer.mozilla.org/ko/docs/Web/CSS/linear-gradient

https://wit.nts-corp.com/2018/11/19/5371

 

Scenario


Maven Pom.xml 파일을 업데이트 한뒤, compile error는 모두 잡았으나 tomcat을 실행할때 계속해서 

java.util.zip.ZipException: invalid LOC header (bad signature)

.....

No naming context bound to this class loader 

위와 같은 에러가 계속해서 떳다. 

에러를 해결하기 위한 삽질에 대해 적어보겠다.

 

Solution


사실

java.util.zip.ZipException: invalid LOC header (bad signature)

에러가 떳을때 구글링을 해보면 가장 많이 나오는 해결 방법은 그냥 maven repository를 삭제했다가 update를 하라고 가장 많이나온다. 하지만 나의경우에는 다 삭제 후 메이븐을 다시업데이트 해도 에러가 계속해서 났다. 그리고 메이븐 업데이트 할때 시간이 엄청나게 오래걸려서 스트레스가 쌓여만 갔다.

가장좋은 방법은 

1. java.util.zip.ZipException 내 ZipException 메소드에 break point를 걸어준다

2.에러가 날때 왼쪽 스택트레이스를 보면 JarFile.getManifestFromReference() 하는 부분이 있다. 그 부분을 더블 클릭해 본다.

Zipexceiption Break point setting 시 starck trace

3.manEntry 변수 내부에 jar를 확이하여 그 jar파일만 삭제 후 다시 받아본다.

위와 같이 하면 통짜로 repository를 삭제 할 필요가 없이 자르만 삭제 후 다시받으면된다

 

manEntry 내부 member 들

 

출처: https://stackoverflow.com/questions/32090921/deploying-maven-project-throws-java-util-zip-zipexception-invalid-loc-header-b

Scenario: 페이징을 할경우 밑에 숫자가 뜨게된다. 만약 Ajax를 쓰지 않을 경우, 서버에서 nowPage 라고 선택된 페이지를 넣어주고 클라이언트에서 받아서 if문에 i와 now page를 찍어주면 활성화된 페이지 번호에 class="active" 를 써주면 된다.

그러나 ajax로하면 비동기로 하기때문에(페이지를 분기하는게 아님), 리플부분만 갱신해주고 page 번호는 다시 안찍어주기떄문에 복잡해졌는데, 단순하게 jquery로 클릭한 부분에 대해서 Active하는 방법을 알 수있엇다

(boot strap 기준)


Solution:

jQuery 0.42 KB
  1.     $(function(){
  2.      var pageBtn = $("ul > li");    //  ul > li 이를 pageBtn 으로 칭한다. (클릭이벤트는 li에 적용 된다.)
  3.       pageBtn .find("a").click(function(){   // pageBtn 에 속해 있는  a 찾아 클릭.
  4.       pageBtn .removeClass("active");     // pageBtn 속에 (active) 클래스를 삭제.
  5.       $(this).parent().addClass("active"); // 클릭한 a에 (active)클래스를 넣는다.
  6.      })
  7.     });




ex) Ajax로 페이지가 분기하지 않고 비동기적으로 댓글내용을 페이징함, 밑에 번호들도 클릭시 active되게 바꿔줌.


Scenario:

AWS에서 EC2에 Ubuntu Tomcat7 웹 프로젝트를 올려서 배포를 하려고 했다.

Window 환경에서 배포를 했을때는 잘 돌아갔는데

Ubuntu 환경으로 변하니 오류가 해결이 안되는 것이었다.

Tomcat7 로그를 확인해보니 다음같은 오류가 계속났다.

Error initializing mybatis. Cause:org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.datasource.DataSourceException: There was an error configuring JndiDataSourceTransactionPool. 

Cause: javax.naming.NamingException: Could not create resource factory instance [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory]



Solutions

Mybatis 쪽에서 오류가 나는건가 하고 내 코드를 열심히 뒤져봤지만,

문제는 

The cause is a issue in the Ubuntu build/package process for Tomcat7. If I understand the issue correctly, Apache builds tomcat-dbcp.jar from binary files, while Ubuntu builds packages only from source. The Ubuntu project ends up needing to change the Java package name, which tends to break things for us poor users. The gory details may be found at the Ubuntu issues list.

The solution I found is to name the data source factory when I define the resource. In one case, I have a META-INF/context.xml file that contains:

이런 이유에서 나는 것 이었다.




factory="org.apache.commons.dbcp.BasicDataSourceFactory" 

단순히 이 한 줄을 context.xml 파일내 Resource에  추가하니 해결 되었다.

이것때문에 몇날을 고생했는지.. ㅠㅠ 

심지어 윈도우로 EC2를 다시구성해야되나 고민했엇다.



Scenario: 클라이언트에서 jsp를 쓸 수 없었고, 세션 정보도 불러올 수 없고, json을 통해서만 서버와 통신 할 수 있었다.

어떤 자료구조를 날리기 위해 List<Map<>>을 Json 으로 바꿔서 날려야만 했고, 받을때도 Json을 받아야만 했다. 엄청 삽질 해서 겨우 해냈다.


Solutions:


1 Json to List<Map<>>


Java 0.42 KB
  1. import org.codehaus.jackson.JsonGenerationException;
  2. import org.codehaus.jackson.map.JsonMappingException;
  3. import org.codehaus.jackson.map.ObjectMapper;
  4.  
  5.     public static String getQuestion() throws JsonGenerationException, JsonMappingException, IOException{
  6.         ObjectMapper objectMapper = new ObjectMapper();
  7.  
  8.         String json = objectMapper.writeValueAsString(questionPool);
  9.  
  10.         System.out.println(json);
  11.        
  12.         return json;
  13.     }



2.List<Map<>>  to Json

Java 0.84 KB
  1.         import org.codehaus.jackson.map.ObjectMapper;
  2.         import org.codehaus.jackson.node.ObjectNode;
  3.         import org.codehaus.jackson.type.TypeReference;

  4.         ObjectNode sessionNode =  (ObjectNode) obj.get(JsonAdaptorObject.TYPE.META);
  5.        
  6.        
  7.         //wow... Tostring 으로 하면 "" 이 붙어서 json list로 인식못함
  8.         // astext 한방에 되버림. tostring을 할경우 더블 쿼테이션이 "" 붙어버려서 망해버렷엇음
  9.         String json = sessionNode.get("quesMapList").asText();
  10.        
  11.         List<HashMap<String, Object>> queList;
  12.         ObjectMapper MAPPER = new ObjectMapper();
  13.  
  14.        
  15.         //""이 붙는 상황에서 고쳤다.
  16.         //astext로 바꾸고 json 형태를 Map List 로 으로 바꿨음
  17.         try {
  18.             System.out.println(">>start");
  19.             queList = MAPPER.readValue(json, new TypeReference<List<HashMap<String, Object>>>() {});
  20.             System.out.println(queList.get(0).get("qNum"));
  21.         } catch (IOException e1) {
  22.             // TODO Auto-generated catch block
  23.             e1.printStackTrace();
  24.         }


+뷰단에서 스트링값으로 온 Jason 값 처리

Sever단에서 String으로 처리해서 Client 단으로 보내야 했기때문에, 다음과 같이 Jason 데이터로 전달되었다.

"[{\"qNum\":\"1\",\"question\":\"아침 9시까지 그린카를  타고 가산동으로\",\"missFlag\":\"true\"},{\"qNum\":\"2\",\"question\":\"목적지 주변에서 미션을  찾으세요\",\"missFlag\":\"ing\"},{\"qNum\":\"3\",\"question\":\"3번쨰 목적지로 가서 QR 코드를 찾아보세요\",\"missFlag\":\"false\"},{\"qNum\":\"4\",\"question\":\"4번째 미션.\",\"missFlag\":\"false\"},{\"qNum\":\"5\",\"question\":\"5번째 미션.\",\"missFlag\":\"false\"}]"


이것을 파싱해주기위해 다음처럼 정규식을 이용해 replace함

JavaScript 0.63 KB
  1. //콜백 펑션임
  2. function(resMIS000){
  3.             //제이선 -> String 시에는 stringify, 제이선 파싱시에는 parse
  4. //          alert(JSON.stringify(resMIS000).replace(/\\/g, ""));
  5.             //Client 단에서 String jason을 파싱해주기 위해서 \과 대괄호를 제거 해주기위해 다음과 같은 정규식적용
  6.             var jsonString = JSON.stringify(resMIS000.body.misList).replace(/\\/g, "").replace(/"\[/g,"\[").replace(/\]"/g,"\]");
  7.             fn_setStatus(JSON.parse(jsonString));
  8. }
  9.  
  10. function fn_setStatus(data) {
  11.     $.each(data, function(idx, val){
  12.         console.log(val.question+" "+idx);
  13.         fn_setTag(idx, val);
  14.     });
  15. }


Scenario: 

┌ Include nav.jspf (login bar, 여기서 bootstrap jsp,css 갖고있음)

 main body.jsp (list)

└ Include Child.jspf (modal)


이런구조로된 jsp 프로젝트에서 body안에 있는 모달에서


모달관련 함수가 절대 안먹는것이었다.

문제는

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> 이게 충돌이 먹어서였는데


어째서인지 body.jsp에서는 드롭다운도 잘되고 딴것도 다 잘되는데 modal 관련 함수만 전혀 안먹는거였다 (단순히 모달 fade in out은 잘됨)


딱 한순간 문제를 해결 할 수있엇는데, child.jspf에서 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> 해주면

모달관련 함수는 먹었지만 문제는 body와 nav에서 부트스트랩관련 함수가 전혀 안먹었다(drop dwon 등등)


특히 이런 모달 콜백 함수가 전혀 안먹는게 나를 미치게 만들었다..

$('#genieModal').on('show.bs.modal',function (e) {

});


콜백을 안쓰면 엄청난 노가다를 해주어야했기에, 모든 방법을 동원해서 찾았지만 결국 안되는 것이엇다.



solution: 그 찰나  jQuery.noConflict(); 라는 기적적인 마법의키워드를 검색으로 알게되었다.


child 관련 <script> 안에 저키워드를 한번 써주니까 모든 충돌이 해결되었다.


Scenario: 동적으로 생성된 a 태그(컨텐츠 제목) 을 클릭하면 삭제를 할 수 있게 하려고했다. on(click,function()) 키워드로 했는데 아무리 해도 안먹는 것이었다. 그래서 차선책으로 동적으로 생성시킬때 onclick='fn_delete(this)' 이런식으로 줘서 삭제를 시키려고했더니, fn_delete 함수에까지는 접근을 하는데 this obj를 죽어도 못찾는 것이었다. 좌절의 연속..





Solutions: 방법은 아주 간단했다 ㅡㅡ;; on 대신 live 키워드를 써주면 된다.


  1.     $('#schedule_area').empty();
  2.     $.ajax({
  3.         type : "POST",
  4.         url : "??????",
  5.         data : "IDX="+pjtId,
  6.         dataType: "json",
  7.         async: false,
  8.         success : function(data, textStatus, xhr) {
  9.             $.each(data, function(key, val){
  10.                 var dayForm = "<div class='media regi-item'>" +
  11.                                 "<a class='thumb-left' name='sch_title_thumb' href='#this' >" +
  12.                                     "<img src='/mobiza/common/getImage.do?IMG_NAME="+val['IMG_NAME']+"' alt='$TITLE'>" +
  13.                                 "</a>" +
  14.                                 "<div class='media-body'>" +
  15.                                     "<h4 class='rs day_detail'>" +
  16.                                         "<a class='be-fc-orange fw-b' id='sch_title' name='sch_title' href='#this' onfocus='this.blur()' '>"+val['SCH_TITLE']+"</a>" +
  17.                                     "</h4>" +
  18.                                     "<p class='rs comment-content'>"+val['SCH_CONTENT']+"</p>" +
  19.                                     "<input id='SCH_IDX' name='SCH_IDX' type='hidden'  value='"+val['PJT_SCH_IDX']+"'>" +
  20.                                 "</div>" +
  21.                                "</div>";               
  22.                
  23.                 $('#schedule_area').append(dayForm)
  24.             });
  25.         },
  26.         error : function(request,status,error) {  
  27.            alert("code:"+request.status+"\n"+"error:"+error);
  28.         }
  29.      });

쿼리 결과에따라 동적으로 태그를 생성하는 ajax


text 0.19 KB
  1.         $("a[name='sch_title'],a[name='sch_title_thumb']").live("click", function(e){ //제목 이나 섬네일 클릭시
  2.             e.preventDefault();
  3.             fn_schDelete($(this));
  4.         });

해결 script

Scenario: 이미지를 웹페이지에서 업로드 후 업로드된 폴더에서 img 태그를 써서 꺼내올려고했는데 여러가지 문제가있었다.

Solutions: 맨처음에는 배포 프로젝트 폴더에만 넣어놓으면 되는줄 알았는데, 생각보다 복잡하다 reponsegetOutputstream 을써주어야한다.



****

9
5985
#224322 Q&A java jsp

이미지 업로드 후 view 할 때 질문입니다.


이클립스+톰캣으로 작업중에 있습니다.

프로젝트가 완료된 후 서비스를 할 때는 war를 뽑아서 톰캣에 디플로이시켜서 구동할 생각입니다.

현재 게시판에시 이미지를 업로드 할 때 진행중인 프로젝트의 workspace에 파일이 업로드 되도록 하였습니다.

업로드경로는 c:/eclipseWorkspace/ProjectName/WebContent/files/
에 올라가도록 하였습니다.

현재 파일 업로드는 정상적으로 되고 있습니다.

한가지 문제가 발생했는데 이미지가 업로드된 게시물을 선택해서 볼 때
그림이 나오지 않더군요. 그런데 이클립스에서 Project Explorer에서 F5를 해주고 나서 다시 게시물을 보면 업로드된 이미지가 잘 나타납니다.

게시물을 올리거나, 수정하고나, 삭제할 때 항상 지금처럼 이클립스 Project Explorer에서 F5를 해주어야 하는건지....

아니면 뭔가 다른 방법이 있다면 알려주셨으면 합니다.
0
1
  • 답변 9

  •  **** 

    흐음... 개발서버의 톰캣에 war 디플로이해서 해봤는데 여기서는 그런거없이 바로바로 되네요.
    이클립스로 톰캣 구동해서 테스트 하는 개발pc에서는 계속 새로고침 해줘야되는건가요?
    0
  •  ****

     

    프로젝트는 WAS의 배포경로에서 실행되게 됩니다.
    이클립스 + 톰캣으로 개발시
    workspace의 소스가 바로 실행되는 것처럼 느껴지지만
    실제로는 이클립스가 소스 변경이 감지될 때마다 자동으로 톰캣 배포 경로로 소스를 복사(배포)해주고
    배포 경로에서 소스가 실행되는 겁니다.
    workspace의 경로와 톰캣에 배포된 소스의 경로는 다르고요.

    그러니까 현재 상황은
    로컬에서는 실행되는 경로(배포 경로)와 업로드 경로(workspace)가 다르기 때문에
    이미지를 찾지 못하는 것이고요,

    개발서버에 올렸을 때는 업로드 경로를 배포 경로 밑의 files로 지정하셨을테니
    이미지가 제대로 보이는 것이겠죠.
    0
  •  ****
     
    아 그리고 로컬에서 실행시
    업로드 후 이클립스의 소스를 새로고침 하면 그 때부터는 제대로 보이는 이유도
    이클립스가 새로고침 하면서 workspace/files에 저장된 이미지를 배포 경로쪽으로 복사해주기 때문에
    그때부터는 제대로 보이는 겁니다.
    0
  •  ****
     
    NG님//답변 감사합니다 ^^. 그 경로를 찾아봐야겠네요!!!
    0
  •  ****

     

    말씀하신대로 경로 찾아내서 거기에 업로드 되도록 했더니 바로바로 됩니다.
    감사합니다!!!
    0
  •  ****

     

    워크스페이스 경로/.metadata/.plugins/org.eclipse.wst.server.core

    톰캣 플러그인의 배포경로입니다.
    요 경로 밑에서 찾아보세요.

    그리고 로컬에서 테스트할 때는 배포되거나 clean할 때마다
    기존에 업로드된 이미지들은 지워질거에요.
    0
  •  ****

     

    NG님//네 말씀하신대로 수정되서 자동으로 reload??하거나 하니까 없어지네요.
    서버에서 war가 새로 디플로이될때도 없어지는데... 이건 방법이 없는 건가요?
    0
  •  ****

     

    그럴 경우
    파일 업로드/다운로드처럼 아예 별도의 디렉토리에 저장하게 한 뒤
    이미지를 response.getOutputStream()에 담아주는 서블릿을 만들어서 불러다 쓰는 방법이 있습니다.

    img 태그의 src 값도 /files/img.jpg 이런식이 아니라
    /imgLoad.do?imgName=img.jpg 처럼 서블릿을 호출하는 식으로 바꾸고요.

    이 방법이 어려우면 배포하기 전에 이미지 업로드 디렉토리를 백업해뒀다가
    배포 후 덮어씌우는 식으로 해야할 겁니다.
    0
  •  ****

     

    NG님//그렇군요. 흐으... 아는게 없다보니 힘들군요. 더 연구해봐야겠습니다.
    0


response 객체를 써서 이미지를 꺼내오는 방법. 좀더 연구를 해봐야 알 듯하다.

Java 0.70 KB
  1. @WebServlet("/files/*")
  2. public class FileServlet extends HttpServlet {
  3.  
  4.     @Override
  5.     protected void doGet(HttpServletRequest request, HttpServletResponse response)
  6.         throws ServletException, IOException
  7.     {
  8.         String filename = URLDecoder.decode(request.getPathInfo().substring(1)"UTF-8");
  9.         File file = new File("/path/to/files", filename);
  10.         response.setHeader("Content-Type", getServletContext().getMimeType(filename));
  11.         response.setHeader("Content-Length"String.valueOf(file.length()));
  12.         response.setHeader("Content-Disposition""inline; filename=\"" + file.getName() + "\"");
  13.         Files.copy(file.toPath(), response.getOutputStream());
  14.     }
  15.  
  16. }






Scenario: 게시판을 만들고나서 이제 글내용을 불러와보니 엔터등 <br> 인식이 안되는 치명적인 현상이 있엇다.

 db에서 불러올때 엔터를 <br>로 인식하게 하는 util은 쉽게 가져올수 있엇는데, 

 <%= utils.getContent(String)%> 이런식으로 써야했다. 나는 db에서 Content를 불러올때 ${dto.content} 이런식으로 불러오는데

 아무리 짱구를 굴려봐도 <%= utils.getContent( ${dto.content} )%> 이런식으로 쓸 수 가 없었다.

그래서 custom el function을 만들기로 했다 (처음엔 1시간이면 만들줄 알았지....)



solution: (아래)


1.먼저 Util파일을 만든다 (이 유틸은 디비에서 글을 불러올때 엔터를 <br>로 대입해주는 유틸이다)

주의점: 만약 bean을 사용하면 메소드를 static으로 선언해줄 필요가 없지만, 우리는 custom el funtion을 만들어야 하기때문에 무조건 static으로 만들어야한다

ContentForm.java

Java 0.56 KB
  1. public class ContentForm {
  2.     public static String getContent(String comment) {
  3.         return br(" ""<br>", comment);
  4.     }
  5.  
  6.     public static String br(String first, String brTag, String comment) {
  7.         StringBuffer buffer = new StringBuffer();
  8.         StringTokenizer st = new StringTokenizer(comment, "\n");
  9.         int count = st.countTokens();
  10.         buffer.append(first);
  11.         int i = 1;
  12.         while (st.hasMoreTokens()) {
  13.             if (== count) {
  14.                 buffer.append(st.nextToken());
  15.             } else {
  16.                 buffer.append(st.nextToken() + brTag);
  17.             }
  18.             i++;
  19.         }
  20.         return buffer.toString();
  21.     }
  22. }


2.tld 파일을 만들어준다

el-funtion.tld

XML 0.82 KB
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2.  
  3. <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  5.    version="2.0">
  6.  
  7.     <description>CommonUtil functions library</description>
  8.     <display-name>CommonUtil functions</display-name>
  9.     <tlib-version>1.1</tlib-version>
  10.     <short-name>mobizaUtil</short-name>
  11.     <uri>tld/el-funtion.tld</uri>
  12.  
  13.     <function>
  14.         <description>글내용 엔터 등, 줄바꿈 인식하게하기</description>
  15.         <name>getContent</name>
  16.         <function-class>경로.ContentForm</function-class>
  17.         <function-signature>java.lang.String getContent(java.lang.String)</function-signature>
  18.     </function>
  19. </taglib>


3. web.xml에 uri와 tld 파일 경로를 맵핑시켜준다 (생략가능)

web.xml

XML 0.25 KB
  1.     <!-- Custom UL TAG을 쓰기위함이다 -->
  2.     <jsp-config>
  3.         <taglib>
  4.             <taglib-uri>
  5.               tld/el-funtion.tld
  6.             </taglib-uri>
  7.             <taglib-location>
  8.              {프로젝트상 실제경로}/el-function.tld
  9.             </taglib-location>
  10.         </taglib>
  11.     </jsp-config>


4.jsp 페이지 내에서 사용예

만약 web.xml에서 맵핑을 하지 않는다면

<%@ taglib uri="WEB-INF/tld/el-funtion.tld" prefix="moutil" %>

이런식으로 실제 파일이 위치한 경로를 맵핑시켜주어도 무방하다.

ex.jsp

  1. HTML 0.12 KB
  1. <%@ taglib uri="tld/el-funtion.tld" prefix="moutil" %>
  2.  
  3.  
  4. <body>
  5.     내용:${moutil:getContent(dto.bContent) }
  6. <body>


Scenario: Instargram 에서 처럼 파일 업로드 메뉴이미지만 누르면 파일첨부 창이뜨고 내이미지를 첨부할려고했다


Solutions:(아래)

myprofile.jsp (html코드 생략)

jQuery 0.98 KB
  1. $(function() {
  2.     //이미지 클릭시 업로드창 실행
  3.     $('#profile_file_add').click(function() {
  4.         console.log('fileadd');
  5.         $("input[name='fileProfile']").click();
  6.        
  7.     })
  8.     //업로드 파일체인지가 됬을경우 실행되는 이벤트  form태그에 fileProfile은 hidden으로 넣어줌
  9.     $("input[name='fileProfile']").change(function(e){
  10.        
  11.         $( "#frm_profile_img" ).submit();
  12.         $("input[name='fileProfile']").val();
  13.         var frm = document.getElementById('profile_file_add');
  14.         frm.method = 'POST';
  15.         frm.enctype = 'multipart/form-data';
  16.         var fileData = new FormData(frm);
  17.      
  18.         // ajax
  19.         $.ajax({
  20.             type:'POST',
  21.             url:'/BoardProject/profileUpdate.ref',
  22.             data:fileData,
  23.             processData: false,
  24.             contentType: false,
  25.             success : function(data, textStatus, xhr) {
  26.                 console.log('success');
  27.             },
  28.             error : function(request,status,error) {  
  29.                alert("code:"+request.status+"\n"+"error:"+error);
  30.             }
  31.         });
  32.     })
  33. })



service 영역.java

Java 1.25 KB
  1. public class ProfileUploadCommand implements BoardCommand {
  2.  
  3.     @Override
  4.     public void execute(HttpServletRequest request, HttpServletResponse response) {
  5.         DAO dao = new DAO();
  6.         HttpSession session = request.getSession();
  7.         String mid=(String)session.getAttribute("mid");
  8.         String contents ="";
  9.         String fileName = "";
  10.         //String profimg = ""; //프로필 이미지
  11.         //**************** File 추가부분****************//
  12.         String pathname = "C:\\dev\\profile";
  13.         File f = new File(pathname);
  14.         if (!f.exists()) {
  15.             // 폴더가 존재하지 않으면 폴더 생성
  16.             f.mkdirs();
  17.         }
  18.         String encType = "UTF-8";
  19.         int maxFilesize = 5 * 1024 * 1024;
  20.  
  21.         // MultipartRequest(request, 저장경로[, 최대허용크기, 인코딩케릭터셋, 동일한 파일명 보호 여부])
  22.         try {
  23.             MultipartRequest mr = new MultipartRequest(request, pathname, maxFilesize, encType, new DefaultFileRenamePolicy());
  24.             fileName = mr.getFilesystemName("fileProfile");
  25.             System.out.println("upload profile mid@@@@@@"+mid);
  26.             System.out.println("upload profile filename@@@@@@"+fileName);
  27.         } catch (IOException e) {
  28.             e.printStackTrace();
  29.         }
  30.         dao.profileUpdate(mid, fileName);
  31.     }
  32.  
  33. }



-----------------------------------------------보너스---------------------------------------------------------

Scenario: db와의통신 없이 내가 첨부한 이미지를 미리보기 할 수 있는기능 추가


Solutions: 아래

파일첨부 폼.html

HTML 5 0.25 KB
  1.     <form  action="write.ref" method="post" enctype="multipart/form-data">
  2.         <input type="file" name="files">
  3.         <div id="holder"></div>
  4.         <textarea rows="5" cols="100" name="contents"></textarea><br>
  5.         <input type="submit" value="글쓰기">
  6.     </form>



  1. <script>
  2. $("input[name='profile_img']").change(function(e){
  3.     e.preventDefault();
  4.  
  5.     var file = this.files[0];
  6.         reader = new FileReader();
  7.    
  8.     reader.onload = function (event) {
  9.         var img = new Image();
  10.         img.src = event.target.result;
  11.         if (img.width > 700 || img.height > 500) { // holder width
  12.           img.width = 700;
  13.           img.height = 500;
  14.         }
  15.         $('#holder').empty();
  16.         $('#holder').append(img);
  17.     };
  18.     reader.readAsDataURL(file);
  19.    
  20.     return false;
  21. });
  22. </script>
  23.  
  24. <!-- 2. DY가 짠 첨부파일 미리보기 소스-->

  25. <script>
  26. var upload = document.getElementsByTagName('input')[0],
  27.     holder = document.getElementById('holder');
  28.  
  29. upload.onchange = function (e) {
  30.     e.preventDefault();
  31.    
  32.     var file = upload.files[0],
  33.         reader = new FileReader();
  34.    
  35.    
  36.     reader.onload = function (event) {
  37.         var img = new Image();
  38.         img.src = event.target.result;
  39.         if (img.width > 700 || img.height > 500) { // holder width
  40.           img.width = 700;
  41.           img.height = 500;
  42.         }
  43.         holder.innerHTML = '';
  44.         holder.appendChild(img);
  45.     };
  46.     reader.readAsDataURL(file);
  47.    
  48.     return false;
  49. };
  50. </script>


+ Recent posts