spring  mvc homepage  스프링 홈페이지 만들기 1

스프링을 이용하여 홈페이지를 제작해볼 예정입니다. 

최대한 간단하게 필요한 결과 위주로 구성해볼 예정입니다.

UI는 https://adminlte.io/themes/v3/pages/layout/top-nav.html를 이용할 예정입니다.

소스코드를 다운로드 받아주세요.
용량

압축을 해제하니 용량이 제법 많으네요. 일단 다운로드한 후 잘 보관해 놓으세요.

STS를 설치해주세요. 그리고 새로운 프로젝트를 시작해요.

스프링프로젝트생성

프로젝트를 생성을 해요. 생성할때 Spring MVC Project로 해주세요. 

서버를 실행해보세요. 톰캣서버로 실행을 할 거예요. 8 버전으로 맞추어 주세요. 

실행을 하면 이런 화면이 보일꺼에요. 

hello world

??? 표도 나오고 그러죠? 이제 utf8환경으로 세팅을 할 건데요. 세팅되어 있는 환경을 복사하는 형태로 진행할게요.

안에 내용은 따로 공부해보세요. 검색하면 잘 나와요. 

처음에 할 일은 pom.xml을 수정할 거예요. 

pom.xml

이 부분을 남기고 모두 첨부한 pom.xml과 같게 수정을 해줘요 안에 필요 없는 내용은 삭제하시면 돼요. 

pom.xml
0.01MB

다음은 web.xml을 수정할게요. 

web.xml
0.00MB

web.xml내용을 복사해주세요.

이제 jsp페이지를 수정할 거예요. 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

 

내용일 텐데요 아래와 같이 수정을 해요. 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

 

서버 폴더 안에 톰캣 8이 있어요 거기에 server.xml이 있는데 이걸 수정할 거예요.

<Context docBase="homepage" path="/" reloadable="true" source="org.eclipse.jst.jee.server:homepage"/></Host>

path를 지우세요. 이러면 localhost:8080으로 접속 시 바로 home.jsp내용이 나와요. 

헬로우 월드가 출력되었죠?

다음은 ADMINLTE3 네이게이션페이지를 출력해볼께요. 

 

참고자료

https://book.naver.com/bookdb/book_detail.nhn?bid=9425458

 

코드로 배우는 스프링 웹 프로젝트

[코드로 배우는 스프링 웹 프로젝트]는 개발 현장에서 사용하는 도구로서 스프링을 취급하는 책으로, SPRING FRAMEWORK(이하 스프링)를 이용해서 ‘웹 프로젝트’를 어떻게 진행하는지를 설명한다. �

book.naver.com

참고카페

https://cafe.naver.com/gugucoding

 

구멍가게코딩단 : 네이버 카페

안녕하세요? 구멍가게 코딩단의 활동을 위한 카페입니다.

cafe.naver.com

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

summernote img 태그 이미지 첨부 스프링

https://summernote.org/ 에가면 사용법등 잘설명되어 있어요.

저는 스프링에서 summernote를 사용하는 방법에대해서 정리할거에요.

일단 summernote를 다운로드 받으세요. 사이트에 가면 잘나와 있어요. 

	<link href="${pageContext.request.contextPath}/resources/editor/summernote.css" rel="stylesheet">
	<script src="${pageContext.request.contextPath}/resources/editor/summernote.js"></script>
	<!-- include summernote-ko-KR -->
	<script src="${pageContext.request.contextPath}/resources/editor/lang/summernote-ko-KR.js"></script>
    

받으셨으면 페이지에 첨부를 해요. 

페이지를 시작하는 부분에 $(document).ready(function() {});

아래코드를 첨부해요.

$('#summernote').summernote({
	    lang: 'ko-KR', // default: 'en-US'
	   	height: 500,                 // set editor height
		minHeight: 500,             // set minimum height of editor
		maxHeight: 500,             // set maximum height of editor
		focus: true,                  // set focus to editable area after initializing summe
		callbacks: {
          onImageUpload: function(files, editor, welEditable) {
            for (var i = files.length - 1; i >= 0; i--) {
              sendFile(files[i], this);
            }
          },
          onChange: function(contents, $editable) {
              console.log('onChange:', contents, $editable);
             
              new_img_list=$(".note-editable .sn_insert_img");
              if(old_img_list!='' &&new_img_list!='')
              {
              	note_image_sync(old_img_list,new_img_list);
              }
              old_img_list= $(".note-editable .sn_insert_img");
              
            },
          onBlur: function() {
              console.log('Editable area loses focus');
            },
          onFocus: function() {
              console.log('Editable area is focused');
            }
        }
	  });
	$("#summernote").summernote({
	    onMediaDelete : function($target, editor, $editable) {
	         alert($target.context.dataset.filename);         
	         $target.remove();
	    }
	}); 

섬머노트 페이지에 가면 설명이 잘되어 있어서 설명은 안하겠어요. 여기서 onImageUpload 부분을 구현해줘야 해요. 

sendFile부분을 구현해야해요. 

function sendFile(file, el) {
    var form_data = new FormData();
    form_data.append('file', file);
    $.ajax({
      data: form_data,
      headers : {
			'X-CSRF-TOKEN': $("#csrf_token").val()
		},
      type: "POST",
      url: '/admin/chart/image_upload',
      cache: false,
      contentType: false,
      enctype: 'multipart/form-data',
      processData: false,
      async: false
    }).done(function( msg ) {
        if(msg.result=='IMAGE_OK')
        {
	        var url = msg.url;
	        id = msg.id;        
	        $(el).summernote('editor.insertImage', url,fun_summernote_imgcallback);
	        $('#imageBoard > ul').append('<li><img src="'+url+'" class="summernoteimg_obj" id="'+id+'" width="100%" height="100%"/></li>');
        }
        else
    	{
        	showmessage("알림","이미지 파일이 아닙니다.",2000,'');
    	}
    });
  }

저는 이미지 파일을 db에 보관을 해요. 

image_upload부분은 이렇게 해요. 

@ResponseBody
		@RequestMapping(value ="/image_upload", method=RequestMethod.POST, produces = "application/json;charset=UTF-8")
		public Map<String, String> update_file_upload(MultipartFile file,HttpServletRequest request)throws Exception{
			Map<String, String[]> paramMap=request.getParameterMap();
			Iterator keyData = paramMap.keySet().iterator();
			CommonData dto = new CommonData();
			while (keyData.hasNext()) {
			    String key = ((String)keyData.next());
			    String[] value = paramMap.get(key);
			    dto.put(key, value[0].toString());        
			    smsp.print_String("key : " + key + ", value : " + value[0].toString());
			} 
			MediaUtils MediaUtils = new MediaUtils();
			String formatName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
			MediaType mType = MediaUtils.getMediaType(formatName);
			BufferedImage resizeimg;
			if(mType!=null)
			{
				BufferedImage srcImg = ImageIO.read(file.getInputStream()); 
				/*
			    if(srcImg.getWidth()>1920) //사이즈 조절 할때
			    {
			    	smsp.print_String("사이즈 조절 1920");
			    	resizeimg = Scalr.resize(srcImg
			    			, Scalr.Method.QUALITY
			    			, Scalr.Mode.FIT_TO_WIDTH
			    			, 1920
			    			,Scalr.OP_ANTIALIAS);
			    	ByteArrayOutputStream baos_re = new ByteArrayOutputStream();
			 	    boolean foundWriter_re = ImageIO.write(resizeimg, formatName.toLowerCase(), baos_re);
			 	    baos_re.flush();
			 		byte[] imageInByte_re = baos_re.toByteArray();
			 		dto.put("mt_contentlength",baos_re.toByteArray().length);
			 		dto.put("mt_data", imageInByte_re);
			 		baos_re.close();
			    }
			    else //사이즈 조절안할때.
			    */ 
			    {	
			    	smsp.print_String("사이즈 조절안함. 1920");
			    	dto.put("mt_contentlength",file.getBytes().length);
			 	    dto.put("mt_data", file.getBytes());
			    }	   
			    BufferedImage destImg = 
			            Scalr.resize(srcImg, 
			            		Scalr.Method.BALANCED, 
			                180,180
			                ,Scalr.OP_ANTIALIAS);
			    ByteArrayOutputStream baos = new ByteArrayOutputStream();
			    boolean foundWriter = ImageIO.write(destImg, "png", baos);
				baos.flush();
				byte[] imageInByte = baos.toByteArray();
				dto.put("mt_s_data", imageInByte);
				baos.close();
			}
			Map<String, String> result = new HashMap<>();
			result.put("result", "NOT_AN_IMAGE");
			if(mType!=null)
			{
			    dto.put("mt_filename",file.getOriginalFilename());
			    dto.put("mt_type",file.getContentType());
			    HttpSession session = request.getSession();
			    Member vo = (Member) session.getAttribute("login");
			    dto.put("mt_input_id", vo.idx);
			    dto.put("mt_update_id", vo.idx);
			    first_service.insert(dto, "File_UpDown_Mapper.insert_editor_image_upload");
			    int idx= first_service.listSearchCount(dto, "File_UpDown_Mapper.select_editor_image_upload");
				result.put("result", "IMAGE_OK");
			    String url = "/editor/get_editor_image/?idx="+idx;
			    String id = ""+idx;
			    result.put("url", url);
			    result.put("id", id);
			    }
		    return result;
		}

db에 바로 넣고 있어요. 

db의 테이블은 이렇게 생겼어요. 

CREATE TABLE `editor_image_table` (
  `idx` int(11) NOT NULL AUTO_INCREMENT COMMENT '게시물 고유키값',
  `mt_uuid` varchar(40) DEFAULT NULL,
  `mt_contentlength` int(11) DEFAULT NULL COMMENT '파일사이즈.',
  `mt_filename` varchar(100) DEFAULT NULL COMMENT '이름',
  `mt_type` varchar(100) DEFAULT NULL COMMENT '파일타입',
  `mt_data` longblob DEFAULT NULL COMMENT '파일내용',
  `mt_s_data` longblob DEFAULT NULL COMMENT '축소파일내용',
  `mt_input_wdate` datetime DEFAULT NULL COMMENT '입력일',
  `mt_input_id` bigint(20) DEFAULT NULL COMMENT '입력ID',
  `mt_update_wdate` datetime DEFAULT NULL COMMENT '최종수정일',
  `mt_update_id` bigint(20) DEFAULT NULL COMMENT '최종수정ID',
  PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='파일정보';

쿼리부분입니다. 

<!-- 이미지파일 업로드 -->
	<insert id="insert_editor_image_upload">	
		INSERT INTO editor_image_table (
						   mt_filename						
						 , mt_type
						 , mt_data
						 <if test="mt_s_data != null">
						 , mt_s_data
						 </if>
						 <if test="uid != null">
						 , mt_uuid
						 </if>
						 , mt_contentlength
						 , mt_input_wdate
						 , mt_input_id
						 , mt_update_wdate
						 , mt_update_id
						 ) 
				     VALUES (
				           #{mt_filename}				         	
				         , #{mt_type}
				         , #{mt_data}
				         <if test="mt_s_data != null">
				         , #{mt_s_data}
				         </if>
				         <if test="uid != null">
						 , #{uid}
						 </if>
				         , #{mt_contentlength}
				         , now()		          
				         , #{mt_input_id}
				         , now()
				         , #{mt_update_id}	         
				         )
	</insert>

이상입니다.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

spring mvc 스프링 바코드 생성 하기 Zxing 사용법

안녕하세요. spring 프로젝트중 바코드를 생성해서 회원에게 날려줘야 할일이 생겼어요. 

그래서 지금 바코드 생성 관련해서 찾아보니 zxing를 사용한 방법이 공개되어 있었어요. 

일단 메이븐에서 라이브러리 다운로드를 위해 설정을 합니다. 

		<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
		<!-- 구글바코드 오픈소스 -->
		<dependency>
		    <groupId>com.google.zxing</groupId>
		    <artifactId>core</artifactId>
		    <version>3.4.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
		<dependency>
		    <groupId>com.google.zxing</groupId>
		    <artifactId>javase</artifactId>
		    <version>3.4.0</version>
		</dependency>

그리고나서 컨트롤러 위치한 곳에 바코드 이미지를 받아가는 코딩을 합니다. 

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

라이브러리를 import를 하고요. 

@RequestMapping(value = "/get_barcode", method = RequestMethod.GET)
	public ResponseEntity<byte[]> get_partner_image(HttpServletRequest request, Model model) throws Exception {
		 smsp.print_String("get_barcode ==>" + "아악."  );
		String text ="https://digital365365.com";
        String _formatName = text;
        text = new String(text.getBytes("UTF-8"), "ISO-8859-1");
      
 		byte[] imageInByte_re = smsp.getBarCodeImage(text, 840, 160);
 		//smsp.print_String(image.toString());
 		HttpHeaders headers = new HttpHeaders(); 
 		String mt_filename = text+".png";
        String formatName = "png";	      
	      MediaType mType = MediaUtils.getMediaType(formatName);
	      //smsp.print_String(mType.toString());
	      if(mType != null){
		        headers.setContentType(mType);
		      }else{
		    	mt_filename = new String(mt_filename.getBytes("UTF-8"), "ISO-8859-1");
		        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		        headers.add("Content-Disposition", "attachment;filename=\""+mt_filename+"\";");
		        headers.add("Content-Transfer-Encoding", "binary");
		      }
       
	      return new ResponseEntity<byte[]>(imageInByte_re, headers,HttpStatus.OK);
	}

바코드 생성코드는 이렇게 있습니다. 

public static byte[] getBarCodeImage(String text, int width, int height) {
		try {
			Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<>();
			hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
			Writer writer = new Code128Writer();
			BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.CODE_128, width, height);
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			MatrixToImageWriter.writeToStream(bitMatrix, "png", byteArrayOutputStream);
			return byteArrayOutputStream.toByteArray();
		} catch (Exception e) {
			return null;
		}
	}

이상 정리해보았습니다. 

<img src="${pageContext.request.contextPath}/cp_a/get_barcode" alt="바코드">

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

SPRING MVC 세팅 설정 시작하기!

SPRING BOOT도 좋지만 저는 SPRING MVC로 프로젝트를 진행을 하는 편이에요.

환경설정 등을 기존에 해놓은 것을 그대로 사용할 수 있어 그런데요.

일단 STS를 실행하고 새로운 작업공간을 설정해요. 

새로운작업공간

전 DENTALAPP이라는 폴더를 작업공간으로 설정했어요. 

스프링 레거시 프로젝트

오른쪽 마우스를 누르고 New -> Spring Legacy Project를 선택해요.

패키지

그럼 새로운 작업 패키지명을 적는데요 저는 com에 제 이름의 약어인 sms와 2019를 붙이고 home이라고 적었어요. 

앱이름

프로젝트 이름을 dentalapp이라고 하였고요.  템플릿은 Spring MVC Project를 선택하였어요. 

컨트롤러

홈컨트롤러 파일과 홈 JSP파일이 생기는데요. 

JSP파일

JSP파일은 페이지를 UTP-8로 사용하겠다는 내용을 추가해줘요. 안 그러면 한글이 깨져서 나와요. 

그럼 프로젝트를 실행해볼까요?

저는 톰캣 8로 설정하고 돌렸어요. 

결과물

결과가 잘 나오고 있네요. 한글도 안 깨지고요. 

앞으로 쭉 프로젝트를 진행 볼게요. 모바일 웹앱을 만들 생각이고요. 안드로이드랑 아이폰으로 패키징을 할 계획이에요. 

여기까지 정리할게요. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

Spring java excel download 스프링 엑셀 다운 poi

SRPING MVC 이미지

안녕하세요. 웹 개발일을 하다 보면 엑셀 파일을 요청받을 일들이 있어요. 

SPRING에서는 아파치 소프트웨어 재단에서 만든 POI를 사용할 수 있어요. 

마이크로소프트 오피스 파일들을 읽고 쓰는 기능을 제공하는데요. 워드, 엑셀, 파워포인트 파일을 지원하고 있어요. 최근 OFFICE OPEN XML FILE FORMATS(*. DOCX,*. XLSX,*. PPTX)등 지원 파일을 늘려가고 있다고 해요. 

처음 메이븐 설정을 해요. 

		<!-- 엑셀파일 -->
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi</artifactId>
		    <version>3.13</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.poi</groupId>
		    <artifactId>poi-ooxml</artifactId>
		    <version>3.13</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.commons</groupId>
		    <artifactId>commons-collections4</artifactId>
		    <version>4.0</version>
		</dependency>

SERVLET-CONTEXT.XML 파일 내용을 찾아보면 InternalResourceViewResolver가 선언되어 있을거에요. 

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

JSP페이지로 이름을 매핑해주는것인데 대부분 설정이 되어 있을 거예요.

저희가 받아야 할 건 JSP페이지가 아니에요. 

XmlViewResolver를 설정해줘야 해요. 조금 귀찮긴 한데 한번 만들어 놓으면 다른 프로젝트에도 복사해서 사용하면 돼요.

<beans:bean id="viewResolver1" class="org.springframework.web.servlet.view.XmlViewResolver">
        <beans:property name="order" value="1"/>
        <beans:property name="location" value="/WEB-INF/views.xml"/>
    </beans:bean>

views.xml파일위치

views.xml파일을 만들어요. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   	<bean id="mr001_exceldownload_View" class="com.sms2019.excel.mr001_exceldownload_View" />
</beans>

views.xml
0.00MB

그리고 소스파일에 views.properties 추가를 해요. 

views.properties

mr001_exceldownload_View.(class)=com.sms2019.excel.mr001_exceldownload_View

views.properties
0.00MB

컨트롤러 부분에 요청받는 부분을 만들어요. 

@RequestMapping(value = "/g402_excel_download", method = RequestMethod.GET)
  public ModelAndView g402_excel_download(HttpServletRequest request, Model model) throws Exception {
	  	Util_list_convert smsp=Util_list_convert.getInstance();
	  	smsp.print_String("/gp/g402_excel_download");
		Map<String, String[]> paramMap=request.getParameterMap();
		paramMap.forEach(
				(key, value) ->  smsp.print_String(key + " : " + value[0])
				);
		Iterator keyData = paramMap.keySet().iterator();
		CommonData dto = new CommonData();	
		paramMap.forEach(
				(key, value) -> {dto.put(key, value[0]);
				smsp.print_String(key + " : " + value[0]);
				model.addAttribute(key,value[0].toString());
				});
	    CommonData data_box = new CommonData();
	    List Title_list = new ArrayList();    
	    Title_list.add("번호");
	    Title_list.add("품목명");
	    Title_list.add("규격");
	    Title_list.add("파트");
	    Title_list.add("수량");
	    Title_list.add("팀");

	    List Title_list_coll = new ArrayList();
	    Title_list_coll.add("rownum");
	    Title_list_coll.add("item_name");
	    Title_list_coll.add("item_standard");
	    Title_list_coll.add("part_division_text");
	    Title_list_coll.add("quantity");
	    Title_list_coll.add("team_code_text");
	    
	    dto.put("exceldown","exceldown");
	    List<Map<String, Object>> list = z_service.select(dto,"Gp2018_Mapper.g402_list_select");
	    ModelAndView mav = new ModelAndView("mr001_exceldownload_View");
	    mav.addObject("Title_list", Title_list);
	    mav.addObject("Title_list_coll", Title_list_coll);
	    mav.addObject("list", list);
	    mav.addObject("Filename", "주문목록");
	    return mav;
  }

엑셀 파일 데이터를 만들어요 db에서 읽어와도 좋고요 엑셀 윗부분을 요청 시 받아와도 되고요 전 컨트롤러를 각각 만들어서 써요. 그래서 타이틀이랑 항목 칼럼 이름 그리고 데이터 그리고 파일 이름 넣어요. 

그럼 MadelAndView에 적힌 부분으로 호출이 되는데요.

package com.danawa.excel;

import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.view.document.AbstractExcelView;

import com.danawa.domain.CommonData;
import com.danawa.util.Util_list_convert;

@Controller
public class mr001_exceldownload_View extends AbstractExcelView {
 
    @Override
    protected void buildExcelDocument(Map<String, Object> model,
            HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
    	Util_list_convert smsp=Util_list_convert.getInstance();
	  	smsp.print_String("Common_exceldownload");
    	String Filename = (String)model.get("Filename");
		String fileName = Filename+".xls";
		fileName = URLEncoder.encode(fileName,"UTF-8");
        response.setContentType("application/ms-excel; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename="+fileName);
        // get data model which is passed by the Spring container
        List<String> Title_list = (List<String>) model.get("Title_list");
        List<String> Title_list_coll = (List<String>) model.get("Title_list_coll");
    	List<CommonData> list = (List<CommonData>) model.get("list");
        // create a new Excel sheet
        HSSFSheet sheet = workbook.createSheet("sheet1");
        sheet.setDefaultColumnWidth(30);
         
        // create style for header cells
        CellStyle style = workbook.createCellStyle();
        CellStyle centerstyle = workbook.createCellStyle();
        CellStyle centerbluestyle = workbook.createCellStyle();
       
        Font font = workbook.createFont();
        font.setFontName("Arial");        
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);
       // style.setFillForegroundColor(HSSFColor.BLACK.index);
       // style.setFillPattern(CellStyle.SOLID_FOREGROUND);
        style.setBorderBottom (HSSFCellStyle.BORDER_THIN);
        style.setBottomBorderColor (HSSFColor.BLACK.index);
        style.setBorderLeft (HSSFCellStyle.BORDER_THIN);
        style.setLeftBorderColor (HSSFColor.BLACK.index);
        style.setBorderRight (HSSFCellStyle.BORDER_THIN);
        style.setRightBorderColor (HSSFColor.BLACK.index);
        style.setBorderTop (HSSFCellStyle.BORDER_THIN);
        style.setTopBorderColor (HSSFColor.BLACK.index);
        //style.setFont(font);        
        //centerstyle.setFillForegroundColor(HSSFColor.WHITE.index);
        //centerstyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerstyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerstyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerstyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerstyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerstyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillForegroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerbluestyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerbluestyle.setFillBackgroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFont(font);    
         
        // create header row
        HSSFRow header = sheet.createRow(0);
        
        int cellCount;
        cellCount=0;
        int columns_length=0;
        //제목 값 세팅 한다. 
        for(String item : Title_list){
        	header.createCell(cellCount).setCellValue(item);
            header.getCell(cellCount).setCellStyle(centerbluestyle);
            cellCount++;
            columns_length++;
    	}
        
        // create data rows
        int rowCount = 1;   
        String sitem_name = null;
        String item_standard = null;
        String sitem_name_replace=null;
        Iterator list_object = list.iterator();	    
        while (list_object.hasNext()) {
        	CommonData e_object = (CommonData) list_object.next();
            HSSFRow aRow = sheet.createRow(rowCount++);
            cellCount=0; 
            
            for(String item : Title_list_coll){
                String value = e_object.get(item);
                smsp.print_String("item : " + value);
                aRow.createCell(cellCount).setCellValue(value);
	            aRow.getCell(cellCount).setCellStyle(centerstyle);            
	            cellCount++;
            }
    	}
        for(int ni=1;ni<=sheet.getLastRowNum();ni++)
        { 
        	sheet.getRow(ni).setHeightInPoints((float)20);
        	 
        }
       
        autoSizeColumns(sheet,sheet.getRow(0).getLastCellNum());
    }
    private void autoSizeColumns(HSSFSheet sheetData, int maxColNum) {
   	 try {
   		 // Autosize columns
   		 int width = 0;
   		 for (int col = 0; col < maxColNum; col++) {
   			 sheetData.autoSizeColumn(col);
   			 int cwidth = sheetData.getColumnWidth(col);
   			 cwidth += 500;
   			 sheetData.setColumnWidth(col, cwidth);
   			 width += cwidth;
   		 }

   		 // calculate zoom factor
   		 int nominator = 45000 * 100 / width;
   		 if (nominator < 100)
   			 sheetData.setZoom(nominator, 100);

   	 } catch (Exception he) {
   		 // No UI, no autosize :(
   	 }
    }
 
}

이렇게 엑셀 내용을 채워 엑셀 파일이 만들어져요.

String Filename = (String)model.get("Filename");
		String fileName = Filename+".xls";
		fileName = URLEncoder.encode(fileName,"UTF-8");
        response.setContentType("application/ms-excel; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition","attachment; filename="+fileName);

파일 이름을 설정하고 utf8로 다운로드돼요.

List<String> Title_list = (List<String>) model.get("Title_list");
        List<String> Title_list_coll = (List<String>) model.get("Title_list_coll");
    	List<CommonData> list = (List<CommonData>) model.get("list");

엑셀 파일의 항목 타이틀과 각 항목의 column의 이름 그리고 데이터 받아와요. 

HSSFSheet sheet = workbook.createSheet("sheet1"); 
        sheet.setDefaultColumnWidth(30);

sheet를 만들어요. 만들 때 이름을 정해줄 수 있어요. 전 sheet1이라고 했어요. 

// create style for header cells
        CellStyle style = workbook.createCellStyle();
        CellStyle centerstyle = workbook.createCellStyle();
        CellStyle centerbluestyle = workbook.createCellStyle();
       

cell 스타일을 미리 만들었어요.  단순해요. style는 흰색의 배경에 검은색의 테두리 선을 가진 것이고요. centerstyle는 중앙 정렬한 흰색 배경에 검은색 테두리 구요. centerbluestyle는 중앙 정렬에 파란 배경을 과 검은색 테두리를 가진 스타일이에요. 

style.setBorderBottom (HSSFCellStyle.BORDER_THIN);
        style.setBottomBorderColor (HSSFColor.BLACK.index);
        style.setBorderLeft (HSSFCellStyle.BORDER_THIN);
        style.setLeftBorderColor (HSSFColor.BLACK.index);
        style.setBorderRight (HSSFCellStyle.BORDER_THIN);
        style.setRightBorderColor (HSSFColor.BLACK.index);
        style.setBorderTop (HSSFCellStyle.BORDER_THIN);
        style.setTopBorderColor (HSSFColor.BLACK.index);        
        centerstyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerstyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerstyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerstyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerstyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerstyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerstyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillForegroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
        centerbluestyle.setAlignment(CellStyle.ALIGN_CENTER);
        centerbluestyle.setFillBackgroundColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setBottomBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setLeftBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setRightBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
        centerbluestyle.setTopBorderColor(HSSFColor.BLACK.index);
        centerbluestyle.setFont(font);    

직관적으로 만들어놓아서 대충 알아보실 거 같아요. 소스량을 줄이려면 함수를 만들면 되겠죠? 그건 직접 해보세요 ^^

 Font font = workbook.createFont();
        font.setFontName("Arial");        
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);

폰트를 따로 선언해서 사용해야 할 일이 있을 경우엔 폰트도 추가해주세요 전 타이틀 부분은 폰트를 다르게 했어요 흰색으로요. ^^

HSSFRow header = sheet.createRow(0);

첫 번째 로우를 만들고요 

 int cellCount;
        cellCount=0;
        int columns_length=0;
        //제목 값 세팅 한다. 
        for(String item : Title_list){
        	header.createCell(cellCount).setCellValue(item);
            header.getCell(cellCount).setCellStyle(centerbluestyle);
            cellCount++;
            columns_length++;
    	}

첫번째 행에 항목 타이틀 값들을 넣어줘요... 

 // create data rows
        int rowCount = 1;   
        String sitem_name = null;
        String item_standard = null;
        String sitem_name_replace=null;
        Iterator list_object = list.iterator();	    
        while (list_object.hasNext()) {
        	CommonData e_object = (CommonData) list_object.next();
            HSSFRow aRow = sheet.createRow(rowCount++);
            cellCount=0; 
            
            for(String item : Title_list_coll){
                String value = e_object.get(item);
                smsp.print_String("item : " + value);
                aRow.createCell(cellCount).setCellValue(value);
	            aRow.getCell(cellCount).setCellStyle(centerstyle);            
	            cellCount++;
            }
    	}

컨트롤러에서 넘겼던 칼럼 항목 이름을 순으로 위치로 해서 셀에 넣어요. 

이상으로 엑셀 파일 다운로드 관련해서 정리해보았습니다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

dropzone 사용법 SPRING MVC 다중파일 멀티파일

웹프로그램 제작시 파일을 여러개 올리고 받아야할 경우가 발생해요.

이경우 dropzone라는 라이브러리를 사용하면 편리하게 구현할수 있어요. 

https://www.dropzonejs.com/

 

Dropzone.js

dropzone.js DropzoneJS is an open source library that provides drag’n’drop file uploads with image previews. It’s lightweight, doesn’t depend on any other library (like jQuery) and is highly customizable. Scroll down!

www.dropzonejs.com

사이트로 이동해서 라이브러리 파일을 다운로드 받아요. 

저는 게시판에 dropzone를 달았어요. 

<table class="table table-write" id="add_mt">
					<colgroup>			
					<col style="width:120px" />
					<col style="width:*" />											
					</colgroup>
					<tr>						
						<th>날짜</th>
						<td>
							<div class="input-group date form_date col-md-5" data-date="" data-date-format="yyyy-MM-dd" data-link-field="dtp_input2" data-link-format="yyyy-MM-dd">
				                    <input class="form-control" size="16" type="text" id ="mt_wdate" name="mt_wdate" value="${mt_wdate}" style="text-align:left;">                   
									<span class="input-group-addon" style="padding:0 10px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc;">
										<span class="glyphicon glyphicon-calendar"></span>
									</span>
				              </div>
						</td>
					</tr>
					<tr>						
						<th>제목</th>
						<td><input type="text" class="form-control" id=mt_subject name="mt_subject" placeholder="제목" value="${mt_subject}" required></td>
					</tr>
					<tr>
						<th>내용</th>
						<td>
							<div id="summernote">${mt_content}</div>
						</td>
					</tr>
					<tr>
						<th>파일첨부</th>
						<td>
							<div id="my_file_upload" class="dropzone">
								<div class="fallback">
									<input name="file" type="file" multiple />
								</div>
							</div>
						</td>
					</tr>
				</table>

summernote와 같이 사용하고 있었는데요. 

dropzone.css와 dropzone.js를 선언해요.

<link href="../../resources/sms/dropzone/dropzone.css" rel="stylesheet">
<script src="../../resources/sms/dropzone/dropzone.js"></script>

그리고 $(document).ready(function() 로 dropzone에 대한 설정을 해요. 

Dropzone.autoDiscover = false;
$(document).ready(function() {	
	edit_mode_note();
	//$("div#my_file_upload").dropzone({ url: "/editor/file_upload" });
	$(".file-dropzone").on('dragover', handleDragEnter);
	$(".file-dropzone").on('dragleave', handleDragLeave);
	$(".file-dropzone").on('drop', handleDragLeave);

	function handleDragEnter(e) {
		this.classList.add('drag-over');
	}

	function handleDragLeave(e) {
		this.classList.remove('drag-over');
	}

	Dropzone.autoDiscover = false;
	
	$("div#my_file_upload").dropzone({ url: "/editor/file_uploads" ,
		addRemoveLinks : true,
			maxFilesize : 256,
		  dictResponseError: 'Error uploading file!',
		  headers: {
		    'X-CSRF-TOKEN': $("#csrf_token").val()
		    , uid : $('#i_uid').val()
		  },
		  params: {
		         uid: $('#i_uid').val()
		    },
		  uploadMultiple : true,
		  thumbnailWidth: 180,
		  thumbnailHeight: 120,
		  parallelUploads: 100,		
		  maxFiles: 255,
		  autoProcessQueue : true,
		  accept: function(file, done) {
			    if (file.name == "") {
			      done("제한사항 없어도 될듯 한뎅?");
			    }
			    else {			    	
			    	done(); 
			    	}
			  },
	init : function() {
		var myDropzone = this;
		var count = myDropzone.options.maxFiles;
		var url = "/editor/file_list";
		var data = JSON.stringify({ 
			uid : $('#i_uid').val()
		});
		
		var callback_init=function (data) {
            if (data.data != '' && data.data != undefined) {
            	var existingFileCount = 0;
                $.each(data.data, function (index, item) {
                    var mockFile = {
                        name: item.mt_filename,
                        size: item.mt_contentlength,
                        seq: item.idx
                    };
                    var filePath = "/editor/get_editor_thumbnail_image/?idx="+item.idx;
                    myDropzone.emit("addedfile", mockFile);
                    myDropzone.emit("thumbnail", mockFile, filePath);
                    myDropzone.emit("success", mockFile);
                    myDropzone.emit("complete", mockFile);                    
                    myDropzone.files.push(mockFile);
                    //file.previewElement.classList.add("dz-processing"); //sms;
                    //file.previewElement.classList.add("dz-complete");
                    existingFileCount = existingFileCount + 1;
                });
                myDropzone.options.maxFiles = myDropzone.options.maxFiles - existingFileCount;
            }
        };
		getPostData(url,data,callback_init);
		
		this.on("maxfilesexceeded", function (file) {
			showmessage("알림","한번에 올릴수 있는 파일의 갯수 제한을 넘었습니다",2000,'');
			myDropzone.removeFile(file);
		});
        
        this.on("success", function( file, resp, formData ){
        	existingFileCount=0;
        	var type = $("#"+id).data("type");
        	if(resp != null && resp != '' && resp != undefined) {
	        	if(resp.data != null && resp.data != '' && resp.data != undefined) {
	    			var existingFileCount = 0;
	    			$.each(resp.data, function(){
	    				if(this.mt_filename==file.name)
	    				{
	    					file.previewElement.appendChild(Dropzone.createElement("<input type='hidden' name='fileId' value='" + this.fileId + "'/>"));
	    					existingFileCount = existingFileCount + 1;
	    				}
	    			});
	    		}
        	}
        	if(file.seq != null && file.seq != '' && file.seq != undefined) {
				file.previewElement.appendChild(Dropzone.createElement("<input type='hidden' name='fileId' value='" + file.seq + "'/>"));
    		}
        });
        
        this.on("removedfile", function (data) {
        	var id = $(data.previewElement).find('input[name=fileId]').val();
    		var sql_state_value = 'delete';
    		var data = JSON.stringify({
    			   sql_state : sql_state_value		 
    			 , idx : id    	
    			 , uid : $('#i_uid').val()
    		   	 , mt_input_id : $('#login_mt_id').val()
    			 , mt_update_id : $('#login_mt_id').val()
    		});
    		var url ='/editor/editor_note_delete_img';
    		getPostData(url,data,null);
    		myDropzone.options.maxFiles = myDropzone.options.maxFiles + 1;
    		if(count < myDropzone.options.maxFiles) myDropzone.options.maxFiles = count;
    	    });
		}
	
	});
	$('.push').click(function() {
		$('.dropzone').each(function() {
			alert("어휴.");
		});
	});


});

headers: {
    'X-CSRF-TOKEN': $("#csrf_token").val()
    , uid : $('#i_uid').val()
  },

스프링부트 사용시 csrf-token을 headers에 넣어주시면 되요.

스프링쪽 컨트롤러는 /file_uploads는 이렇게 만들었어요. 

//멀티파일..
  @ResponseBody
  @RequestMapping(value ="/file_uploads", method=RequestMethod.POST, 
                  produces = "application/json;charset=UTF-8")
  public  Map<String, List<Map<String, String>>> file_uploads(MultipartFile nfile,MultipartHttpServletRequest  request)throws Exception{
	
	String uid=null;
	Map<String, String[]> paramMap1=request.getParameterMap();
	 Iterator keyData1 = paramMap1.keySet().iterator();	
    while (keyData1.hasNext()) {
        String key = ((String)keyData1.next());
        String[] value = paramMap1.get(key);
        logger.info("key : " + key + ", value : " + value[0].toString());
        if(key.equals("uid"))
        {
        	uid=value[0].toString().trim();
        }
    }    
	Map <String, MultipartFile > paramMap = request.getFileMap ();
	 Iterator keyData = paramMap.keySet().iterator();
	 CommonData dto = new CommonData();
	 
	 Map<String, List<Map<String, String>>> result = new HashMap<>();
	 List<Map<String, String>> data_list = new ArrayList();
	 
    while (keyData.hasNext()) {
    	Map<String, String> data = new HashMap<>();
        String key = ((String)keyData.next());
        MultipartFile file = paramMap.get(key);
        
        file_upload_ex(dto, data, file,uid);  //return ResponseEntity.ok().body(result);
        data_list.add(data);
        dto.clear();
    }
    result.put("data", data_list);
    return result;
  }

file_upload_ex부분은 이렇게 만들었어요. 

private String file_upload_ex(CommonData dto, Map<String, String> result, MultipartFile file, String uid)
		throws IOException, Exception {
	logger.info("originalName: " + file.getOriginalFilename());
    MediaUtils MediaUtils = new MediaUtils();
    String formatName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
    MediaType mType = MediaUtils.getMediaType(formatName);
    if(mType!=null)
    {
	    UploadFileUtils f_util = new UploadFileUtils();
	    BufferedImage  descimg = f_util.cropImageSquare(file.getBytes());
	    BufferedImage srcImg = ImageIO.read(file.getInputStream());
	    BufferedImage destImg = 
	            Scalr.resize(srcImg, 
	            		Scalr.Method.BALANCED, 
	                180,180
	                ,Scalr.OP_ANTIALIAS);
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    boolean foundWriter = ImageIO.write(destImg, "png", baos);
		baos.flush();
		byte[] imageInByte = baos.toByteArray();
		dto.put("mt_s_data", imageInByte);
		baos.close();
    }
	
	    dto.put("mt_filename",file.getOriginalFilename());
	    dto.put("mt_type",file.getContentType());
	    dto.put("mt_contentlength",file.getBytes().length);
	    dto.put("mt_data", file.getBytes());
	    dto.put("uid", uid);
	    
	
	    z_service.insert(dto, "File_UpDown_Mapper.insert_editor_image_upload");    
	    int idx= z_service.listSearchCount(dto, "File_UpDown_Mapper.select_editor_image_upload");
		result.put("result", "UPDATE_OK");
	    String url = "/editor/get_editor_image/?idx="+idx;
	    String id = ""+idx;
	    result.put("url", url);
	    result.put("id", id);	    
	    result.put("fileId", id);
	    result.put("mt_filename", file.getOriginalFilename());
	    result.put("mt_type", file.getContentType());
	    result.put("formatName", formatName);	 
	    result.put("uid", uid);	    
	    return id;
}

/file_list 쪽 컨트롤러 에요. 

@RequestMapping("/file_list")
public Map<String, List<Map<String, Object>>> file_list(@RequestBody CommonData dto) throws Exception {
	  Iterator keyData = dto.keySet().iterator();
      while (keyData.hasNext()) {
          String key = ((String)keyData.next());
          String value = dto.get(key);          
          logger.info("key : " + key + ", value : " + value);
      }
      List<Map<String, Object>> list = z_service.select(dto, "File_UpDown_Mapper.get_editor_image_uid_list");
      Map<String, List<Map<String, Object>>> result = new HashMap<>();
      result.put("data", list);
      return result;
  
}

/get_editor_thumbnail_image 컨트롤러 에요. 

@RequestMapping(value = "/get_editor_thumbnail_image", method = RequestMethod.GET)
  public ResponseEntity<byte[]> get_thumbnail_image(HttpServletRequest request, Model model) throws Exception {
	  	 MediaUtils MediaUtils = new MediaUtils();
		 Map<String, String[]> paramMap=request.getParameterMap();		 
		 Iterator keyData = paramMap.keySet().iterator();
		 CommonData dto = new CommonData();
	     while (keyData.hasNext()) {
	         String key = ((String)keyData.next());
	         String[] value = paramMap.get(key);
	         dto.put(key, value[0].toString());        
	         logger.info("key : " + key + ", value : " + value[0].toString());
	     }
	     List<Map<String, Object>> result_list;
	     result_list=z_service.select(dto,"File_UpDown_Mapper.get_editor_thumbnail_image");
	     /*
	     if(result_list.size() < 1)
	     {
	    	 dto.put("idx", "108");
	    	 result_list=z_service.select(dto,"File_UpDown_Mapper.get_editor_image");
	     }
	     */
	     logger.info(""+result_list.size());
	     if(result_list.size() > 0)
	     {
	    	  Iterator list_object = result_list.iterator();
	          Map<String, Object> e_object = (Map<String, Object>) list_object.next();
	          
	          String idx = e_object.get("idx").toString();
	          String mt_filename = (String)e_object.get("mt_filename");
	          byte[] mt_data = (byte[])e_object.get("mt_s_data");	
	          HttpHeaders headers = new HttpHeaders(); 
	          mt_filename = URLEncoder.encode(mt_filename,"UTF-8");
  	        //response.setContentType("application/ms-excel; charset=UTF-8");
  	        //response.setCharacterEncoding("UTF-8");
  	       // response.setHeader("Content-Disposition","attachment; filename="+mt_filename);
	          String formatName = mt_filename.substring(mt_filename.lastIndexOf(".")+1);	      
		      MediaType mType = MediaUtils.getMediaType(formatName);
		      if(mType != null){
			        headers.setContentType(mType);
			      }else{
			    	   String icon_idx= "1";
			    	   formatName = formatName.toUpperCase();
			    	   if(formatName.equals("TXT"))
			    	   {
			    		   icon_idx = "9";
			    	   }
			    	   else if(formatName.equals("XLS")||formatName.equals("XLSX")||formatName.equals("XLSM")||formatName.equals("XLSB")||formatName.equals("XLTX")||formatName.equals("XLTM"))
			    	   {
			    		   icon_idx = "2";
			    	   }
			    	   else if(formatName.equals("MP3"))
			    	   {
			    		   icon_idx = "3";
			    	   }
			    	   else if(formatName.equals("MP4"))
			    	   {
			    		   icon_idx = "4";
			    	   }
			    	   else if(formatName.equals("PDF"))
			    	   {
			    		   icon_idx = "5";
			    	   }
			    	   else if(formatName.equals("PPT")||formatName.equals("PPTX"))
			    	   {
			    		   icon_idx = "6";
			    	   }
			    	   else if(formatName.equals("XML"))
			    	   {
			    		   icon_idx = "7";
			    	   }
			    	   else if(formatName.equals("ZIP"))
			    	   {
			    		   icon_idx = "8";
			    	   }
			    	   else if(formatName.equals("DOC"))
			    	   {
			    		   icon_idx = "10";
			    	   }
			    	   dto.put("idx", icon_idx);
			    	   result_list=z_service.select(dto,"File_UpDown_Mapper.get_editor_thumbnail_image");
			    	   if(result_list.size() > 0)
				  	   {
				  	    	  list_object = result_list.iterator();
				  	          e_object = (Map<String, Object>) list_object.next();
				  	          
				  	          idx = e_object.get("idx").toString();
				  	          mt_filename = (String)e_object.get("mt_filename");
				  	          mt_data = (byte[])e_object.get("mt_s_data");	
				  	          headers = new HttpHeaders(); 
				  	          formatName = mt_filename.substring(mt_filename.lastIndexOf(".")+1);	      
				  		      mType = MediaUtils.getMediaType(formatName);
				  		      if(mType != null){
				  		    	  headers.setContentType(mType);
				  		      }
				  	   }
			      }
	         
		      return new ResponseEntity<byte[]>(mt_data, headers,HttpStatus.OK);
	      }
	     return new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
  	}

저는 위에 등록된파일들을 썸네일 아이콘으로 등록해뒀어요. 파일종류에 따라서 아이콘을 다르게 보이게 할려구요.

/editor_note_delete_img 파일 삭제 컨트롤러 에요.

  @RequestMapping("/editor_note_delete_img")
  public Map<String, String> editor_note_delete_img(@RequestBody CommonData dto) throws Exception {
	  Map<String, String> paramMap = new HashMap<>();
	  
	  Iterator keyData = dto.keySet().iterator();
      while (keyData.hasNext()) {
          String key = ((String)keyData.next());
          String value = dto.get(key);          
          logger.info("key : " + key + ", value : " + value);
      }
      z_service.update(dto, "File_UpDown_Mapper.editor_note_delete_img");
      paramMap.put("result", "IMAGE_DELETE_OK");     
      return paramMap;
  }

파일다운로드는 게시판을 읽어올때 받아와요. 

<div class="view">
				<input type="hidden" class="form-control" id="i_idx" value="${idx}">
				<input type="hidden" class="form-control" id="i_uid" value="${uid}">
				<input type="hidden" class="form-control" id="mt_class" value="${mt_class}">
				<br style="clear: both">
				<!-- 
				<h3 style="margin-bottom: 25px;">뭘 이렇게 까지 자료가.. @@</h3>
				-->
				<div id="mt_subject" class="title">
					${mt_subject}
					<!-- input type="text" class="form-control" id=mt_subject name="mt_subject" placeholder="제목" value="${mt_subject}" required-->
				</div>
				<div id="date" class="date">
					${mt_wdate}
				</div>
				<div id="summernote" class="contents">
					${mt_content}
					<!--  div id="summernote">${mt_content}</div-->
				</div>
               <!-- 파일정보에요. -->
				<div id="mt_file_list" class="filt_list">
					<p class="attachment">첨부파일 다운로드</p>
							
					<c:forEach items="${file_list}" var="file_list"  varStatus="status">
						<a href="/editor/get_editor_image/?idx=${file_list.idx}" download="${file_list.mt_filename}">
						<img src="/editor/get_editor_thumbnail_image/?idx=${file_list.idx}"/>
						${file_list.mt_filename}
						</a>						
					</c:forEach>						
				</div>				  
			</div>

첨부파일 다운로드에서 파일리스트를 가져와서 뿌려주고 아이콘을 클릭하면 다운로드 되요. 

@RequestMapping(value = "/get_editor_image", method = RequestMethod.GET)
  public ResponseEntity<byte[]> get_image(HttpServletRequest request, Model model) throws Exception {
	  	 MediaUtils MediaUtils = new MediaUtils();
		 Map<String, String[]> paramMap=request.getParameterMap();		 
		 Iterator keyData = paramMap.keySet().iterator();
		 CommonData dto = new CommonData();
	     while (keyData.hasNext()) {
	         String key = ((String)keyData.next());
	         String[] value = paramMap.get(key);
	         dto.put(key, value[0].toString());        
	         logger.info("key : " + key + ", value : " + value[0].toString());
	     }
	     List<Map<String, Object>> result_list;
	     result_list=z_service.select(dto,"File_UpDown_Mapper.get_editor_image");
	    
	     logger.info(""+result_list.size());
	     if(result_list.size() > 0)
	     {
	    	  Iterator list_object = result_list.iterator();
	          Map<String, Object> e_object = (Map<String, Object>) list_object.next();
	          
	          String idx = e_object.get("idx").toString();
	          String mt_filename = (String)e_object.get("mt_filename");
	          mt_filename = URLEncoder.encode(mt_filename,"UTF-8");
	          byte[] mt_data = (byte[])e_object.get("mt_data");	
	          HttpHeaders headers = new HttpHeaders(); 
	          String formatName = mt_filename.substring(mt_filename.lastIndexOf(".")+1);	      
		      MediaType mType = MediaUtils.getMediaType(formatName);
		      if(mType != null){
			        headers.setContentType(mType);
			      }else{
			    	mt_filename = new String(mt_filename.getBytes("UTF-8"), "ISO-8859-1");
			        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			        headers.add("Content-Disposition", "attachment;filename=\""+mt_filename+"\";");
			        headers.add("Content-Transfer-Encoding", "binary");
			      }
	         
		      return new ResponseEntity<byte[]>(mt_data, headers,HttpStatus.OK);
	      }
	     return new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
  	}
  

이상으로 dropzone.js를 사용하여 파일을 업로드 삭제 하고 다운로드 하는 것을 해보았어요.

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

스프링 에러java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

컴퓨터 사용계정을 몇일전에 기본으로 변경했어요.

그랬더니 프로젝트 실행할려니 여러문제를 겪게 되었는데요. 

기존 작성한 프로젝트를 열었어요. 메이븐을 업데이트 했어요.

Maven  -> Update Project

프로젝트를 실행하니 에러가 발생합니다. 

java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

구글검색을 하니까 문제 해결법이 나왔어요. 

Deployment Assembly

프로젝트 설정에서 Deployment Assembly에 Maven Dependencies를 추가해야 합니다. 

add버턴을 눌러주세요.

NEW Assembly Directive

java build path entries를 눌러주세요. 

NEW Assembly Directive

Maven Dependencies 선택하고 Finish 를 눌러주세요. 

Deployment Assembly

Maven Dependencies 가 추가된 것을 확인할수 있습니다. 

닫고 다시 실행을 해보세요. 

저는 추가로 

Lambda expressions are allowed only at source level 1.8 or above

이게 뜨더라구요. 아.. 자바 버전 1.8로 설정했어요. 

Java Compiler

저장하고 실행하니 다시 작동했어요. 

참고 사이트는 아래 사이트입니다. 

https://jaeu0608.tistory.com/155

 

[Error] Eclipse에서 Tomcat 실행시 에러 Error configuring application listener of class org.springframework.web.context.ContextLoaderLis

Eclipse에서 Tomcat 구동 에러 ( maven 사용시 ) 심각: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener java.lang.ClassNotFoundException: org.spring..

jaeu0608.tistory.com

수고하세요.

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

홈페이지를 구축하다보면 기존 도메인과 개발도메인 로컬 도메인등 여러 주소를 사용할 경우가 있습니다.

저의 경우 홈페이지 구매후 신규 개발을 들어 갔는데 이름역시 디지털아트에서 디지털365치과의원으로 변경되어 

홈페이지를 신규개발한후 365에 맞는 도메인 https://digital365365.com/ 를 구매하여 설정하였고

기존에 운영중인던 도메인 dadentalclinic.com 도메인과 디지털365치과.com 등을 추가로 설정하였습니다.

그런데 블로그나 사이트 등록시 https://digital365365.com/ 로 하면 좋았을텐데 여러가지 도메인들을 사용하게 되었습니다.

그래서 도메인을 임의로 통합시키는 작업을 해주었습니다. 

<beans:bean id="metaInterceptor" class="com.sms2019.interceptor.MetaInterceptor"></beans:bean>

인터셉터 를 하나 만들어 줍니다. 

인터셉터 내용은 아래와 같습니다.

String m_url = request.getRequestURL().toString();
		smsp.print_String("m_url :" + m_url);
		if(m_url.contains("검사주소 넣기"))
		{
			smsp.print_String("바른주소");
		}
		else if(m_url.contains("http://localhost"))
		{
			smsp.print_String("로콜주소");
		}
		else
		{
			smsp.print_String("그외 주소다.");
			String new_addr = "https://digital365365.com"+originalURL;
			response.sendRedirect(new_addr);
		}

이상입니다. 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

범일동 수치과 홈페이지를 새로 작성하고 있었습니다. 

http://soo-dent.com/

 

부산 범일동 수치과의원

부산 범일동 치과 임플란트 틀니 사랑니 충치치료 신경치료 보철치료 심미치료 스케일링, 부산임플란트, 서면임플란트, 지르코니아

soo-dent.com

인스타 연동이 안되어 있습니다. 인스타를 사진을 가져와 볼려고 했습니다.

기존 인스타그램 가져오는 api가 지원이 중단되었습니다. 

https://www.instagram.com/developer/

 

Instagram Developer Documentation

 

www.instagram.com

인스타그램 중단문구

 Instagram Basic Display API뭔가 싶어 들어가서 따라해보니 잘 안되어 있네요.  

가이드문서가 정리가 잘 안되어 있어서 구글검색을해보니 크롤링해서 사진을 가져오는 분들이 보였습니다.

저도 크롤링으로 가져오기로 합니다. 

일단 크롤링으로 데이터를 가져와보니 인스타내용이 보이지 않았습니다.

인스타는 자바스크립트소스를 보내주고 사용자환경에서 스크립트를 실행하여 데이터를 받아오는 형태입니다.. 

셀레니움으로 하는 방법이 있던데 일반 사람이 접속해서 스크립트가 실행된후 브라우저 데이터값을 가져올수 있었습니다.

일종의 자동화 도구인데 자바역시 지원하여 정리 합니다. 

셀레니움을 받아 설치를 합니다. 

https://www.seleniumhq.org/ 에서 윈도우 버전의 셀레니움을 받습니다. 

<!-- 크롬 셀리니움 -->
		
		<dependency>
	        <groupId>org.seleniumhq.selenium</groupId>
	        <artifactId>selenium-java</artifactId>
	        <version>3.141.59</version>
	    </dependency>

pom.xml 에 추가합니다. 

   //WebDriver
	    private WebDriver driver;
	    private WebElement element;
	    //Properties
	    public static final String WEB_DRIVER_ID = "webdriver.chrome.driver";
	    public static final String WEB_DRIVER_PATH = "chromedriver.exe";

WEB_DRIVER_PATH 를 잘설정합니다.

 System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);
	        driver = new ChromeDriver();
	        base_url = "https://www.instagram.com/soodental9/";
   driver.get(base_url);

이러면 인스타그램 페이지 내용을 가져옵니다. 

 Document doc = Jsoup.parse(driver.getPageSource());
	            // HTML 문서의 타이틀 추출하기
	    		System.out.println("HTML TITLE : " + doc.title());

가져온내용을 JSOUP 를이용하여 파싱을 합니다. 

크롬디버그모드로 본 소스

소스에서 가져와야될 부분을 찾습니다. 

Elements tables = doc.select(".ySN3v"); //클래스..
	    		Elements linksOnPage = tables.select(".v1Nh3.kIKUG._bz0w"); //클래스..

데이터를 가져와서 출력해보았습니다. 

int i=1;
				 for (Element page : linksOnPage) {
					System.out.println("count : "+i++);
					Element link = page.select("a").first();
					String linkHref = link.attr("href"); 
					System.out.println("a href : "+base_url+linkHref);
					Element img = page.select("img").first();
					String imgtag = img.outerHtml();
					System.out.println("img : "+imgtag);
				 }

인스타 그램 내용.

테스트 페이지를 만들어서 위내용을 붙여 넣어 봅니다. 

이미지가 잘 보이네요.

img 태그와  a태그를 db에 넣어서 불러와서 사용하면 되겠습니다. 내용갱신은 하루에 한번 하도록 하면 되겠네요.

아래는 소스 전체 내용입니다. 

package com.sms2019.da;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class instagram_Selenium {
	
	 public static void main(String[] args) {
		 
	        instagram_Selenium selTest = new instagram_Selenium();
	        selTest.crawl();
	    }
	 
	    
	    //WebDriver
	    private WebDriver driver;
	    private WebElement element;
	    //Properties
	    public static final String WEB_DRIVER_ID = "webdriver.chrome.driver";
	    public static final String WEB_DRIVER_PATH = "chromedriver.exe";
	    
	    //크롤링 할 URL
	    private String base_url;
	    public instagram_Selenium() {
	        super();
	        //System Property SetUp
	        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);
	        driver = new ChromeDriver();
	        base_url = "https://www.instagram.com/soodental9/";
	    }
	 
	    public void crawl() {
	        try {
	            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
	        	int waittime=10;
	            driver.get(base_url);
	            JavascriptExecutor js = (JavascriptExecutor) driver;
	          
	            //System.out.println(driver.getPageSource());
	            Document doc = Jsoup.parse(driver.getPageSource());
	            // HTML 문서의 타이틀 추출하기
	    		System.out.println("HTML TITLE : " + doc.title());
	    		Elements tables = doc.select(".ySN3v"); //클래스..
	    		Elements linksOnPage = tables.select(".v1Nh3.kIKUG._bz0w"); //클래스..
	    		int i=1;
				 for (Element page : linksOnPage) {
					System.out.println("count : "+i++);
					Element link = page.select("a").first();
					String linkHref = link.attr("href"); 
					System.out.println("a href : "+base_url+linkHref);
					Element img = page.select("img").first();
					String imgtag = img.outerHtml();
					System.out.println("img : "+imgtag);
				 }
				 System.out.println("======================================================");
	    
	        } catch (Exception e) {
	            
	            e.printStackTrace();
	        
	        } finally {
	            driver.close();
	        }
	 
	    }
}
블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,

이클립스 흰색 에디터 배경이 눈이 아픈경우가 있다. 

이럴때 다크테마를 사용하면 편리하다. 

이클립스 상단 메뉴중 Window -> Preferences 누른다.

메뉴

다음 General -> Appearance -> Theme

메뉴중 dark를 누르면 색상이 변경된다. 

 

블로그 이미지

은호아빠

여행, 맛집, 일상, 프로그래밍, 개발자, 윈도우, 웹, jsp, spring, db, mysql, oracle, c#

,