File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package itn.let.kakao.kakaoComm.kakaoApi;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import egovframework.rte.fdl.property.EgovPropertyService;
import itn.com.cmm.service.EgovFileMngService;
import itn.com.cmm.service.EgovFileMngUtil;
import itn.com.cmm.service.FileVO;
import itn.let.kakao.kakaoComm.KakaoReturnVO;
import itn.let.kakao.kakaoComm.KakaoVO;
import itn.let.mail.service.StatusResponse;
import itn.let.utl.fcc.service.EgovStringUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component("kakaoApiImageUpload")
public class KakaoApiImageUpload {
/** 비즈 URL */
@Value("#{globalSettings['Globals.mjon.biz.url']}")
private String mjonBizUrl;
/** 비즈 회원 아이디 */
@Value("#{globalSettings['Globals.mjon.biz.id']}")
private String mjonBizId;
/** 비즈 회원 API 키*/
@Value("#{globalSettings['Globals.mjon.biz.kakao.apiKey']}")
private String mjonBizKakaoApiKey;
@Resource(name = "propertiesService")
protected EgovPropertyService propertyService;
/** 첨부파일 저장경로 */
@Value("#{globalSettings['Globals.file.saveDir']}")
private String fileSaveDir;
@Resource(name="EgovFileMngUtil")
private EgovFileMngUtil fileUtil;
@Resource(name="EgovFileMngService")
private EgovFileMngService fileMngService;
/**
* @Method Name : kakaoApiImageUpload
* @작성일 : 2023. 1. 19.
* @작성자 : 우영두
* @Method 설명 : 친구톡 이미지 등록
*/
public Map<String, String> kakaoApiImageUpload(KakaoVO kakaoVO, Map<String, MultipartFile> files, int fileKeyParam) throws Exception {
Map<String, String> resultMap = new HashMap<String, String>();
try {
int fileKey = fileKeyParam;
String storePathString = propertyService.getString("Globals.fileStorePath");
File saveFolder = new File(storePathString);
if (!saveFolder.exists() || saveFolder.isFile()) {
saveFolder.mkdirs();
}
List<MultipartFile> tmp = new ArrayList<MultipartFile>(files.values());
ListIterator<MultipartFile> itr = tmp.listIterator(tmp.size());
MultipartFile file;
String filePath = "";
FileVO fvo;
File imgFile = null;
String newName = "";
String fileExt = "";
while (itr.hasPrevious()) {
file = itr.previous();
String orginFileName = file.getOriginalFilename();
//--------------------------------------
// 원 파일명이 없는 경우 처리
// (첨부가 되지 않은 input file type)
//--------------------------------------
if ("".equals(orginFileName)) {
continue;
}
////------------------------------------
int index = orginFileName.lastIndexOf(".");
fileExt = orginFileName.substring(index + 1);
newName = EgovStringUtil.getTimeStamp() + fileKey;
long _size = file.getSize();
//이미지 파일 처리라서 확장자까지 모두 붙여서 파일 생성 함
if (!"".equals(orginFileName)) {
filePath = saveFolder + File.separator + newName + "." + fileExt;
file.transferTo(new File(filePath));
File newFile = new File(filePath);
InputStream inputStream = new FileInputStream(newFile);
Image img = new ImageIcon(newFile.toString()).getImage(); // 파일 정보 추출
int orgWidth = img.getWidth(null);
int orgHeight = img.getHeight(null);
long bytes = file.getSize();
long kilobyte = bytes / 1024;
long megabyte = kilobyte / 1024;
//일반이미지, 와이드 이미지 타입별 용량, 크기 체크
String imgType = kakaoVO.getImageType();
/*
*
!기본 이미지
파일규격 : JPG, JPEG, PNG 만 가능/ 용량 최대 500KB
권장 사이즈 : 720px X 720px(가로 500px 미만, 가로:세로 비율이 2:1 미만 또는 3:4 초과 시 업로드 불가)
!와이드 이미지
파일규격 : JPG, JPEG, PNG 만 가능/ 용량 최대 2MB 사이즈 : 800px X 600px
*
* */
if(imgType.equals("W")) {
if(orgWidth != 800 && orgHeight != 600) {//와이드 이미지인 경우 800 X 600 사이즈만 등록 가능함.
resultMap.put("code", "405");
resultMap.put("msg", "와이드 이미지 크기는 800px X 600px 이어야 합니다.");
return resultMap;
}else if(megabyte > 2) {//와이드 이미지 최대 용량은 2MB
resultMap.put("code", "405");
resultMap.put("msg", "와이드 이미지 용량은 2MB 이내여야 합니다.");
return resultMap;
}
}else {//일반 이미지 처리
//일반 이미지 최대 크기는 500KB를 넘을 수 없다. 실제 498KB여도 500이 넘었다고 등록이 안됨. ㅋ
if(kilobyte > 497) {
resultMap.put("code", "405");
resultMap.put("msg", "파일 최대 용량은 초과하였습니다. 이미지 최대 용량은 500KB를 초과할 수 없습니다.");
return resultMap;
}else if(orgWidth < 500) {//가로 사이즈가 500px 미만이면 안됨
resultMap.put("code", "405");
resultMap.put("msg", "일반 이미지의 최소 가로 사이즈는 500px 이상이어야 합니다.");
return resultMap;
}
//일반 이미지 권장사이즈 초과시 리사이즈 처리 후 저장
int MAX_WIDTH = 720;
int MAX_HEIGHT = 720;
if(orgWidth > 720 || orgHeight > 720) {
if (orgWidth > MAX_WIDTH) {
orgHeight = (int) (orgHeight * (MAX_WIDTH / (float) orgWidth));
orgWidth = MAX_WIDTH;
}
if (orgHeight > MAX_HEIGHT) {
orgWidth = (int) (orgWidth * (MAX_HEIGHT / (float) orgHeight));
orgHeight = MAX_HEIGHT;
}
//이미지 리사이징 요청
EgovFileMngUtil fileMngUtil = new EgovFileMngUtil();
BufferedImage resizedImage = fileMngUtil.resize(inputStream ,orgWidth , orgHeight );
//리사이징된 파일 덮어쓰기
ImageIO.write(resizedImage, "jpg", new File(filePath));
}
}
imgFile = new File(filePath);
}
}
if(imgFile.exists()) {//파일이 존재하면 카카오로 전송 처리
//첨부파일 등록 API 전송 요청
String apiUrl = "/v3/kakao/image/upload";
String sendUrl = mjonBizUrl+ apiUrl;
String fullFileName = newName + "." + fileExt;
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(sendUrl);
HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", "test")
.addTextBody("link", "https://maaa.com")
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath),ContentType.MULTIPART_FORM_DATA,fullFileName)
.build();
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
String result = "";
String statusCode = Integer.toString(response.getStatusLine().getStatusCode());
if(statusCode.equals("200")) {
result = EntityUtils.toString(response.getEntity());
result = new String(result.getBytes("iso-8859-1"));//한글 깨짐 현상이 있어서 변환 해줌.
JSONParser parser = new JSONParser();
Object obj = parser.parse(result);
JSONObject object = (JSONObject) obj;
String code = object.get("code").toString();
String msg = object.get("message").toString();
String imgUrl = "";
log.info(" : code :: [{}]", code);
if(code.equals("200")) {
imgUrl = object.get("image").toString();
}
resultMap.put("code", code);
resultMap.put("msg", msg);
resultMap.put("imgUrl", imgUrl);
}else {
System.out.println("오류 발생");
}
httpClient.close();
}
}catch (Exception e) {
System.out.println("kakaoApiImageUpload API Error !!! " + e);
resultMap.put("code", "400");
resultMap.put("msg", "친구톡 이미지 등록에 오류가 발생하였습니다.");
resultMap.put("imgUrl", "");
return resultMap;
}
return resultMap;
}
/**
* @methodName : kakaoApiImageUpload_advc
* @author : 이호영
* @date : 2025. 6. 4.
* @description : kakaoApiImageUpload 수정
* @return : StatusResponse
* @param kakaoVO
* @param files
* @param i
* @return
* @throws Exception
*
*/
public StatusResponse kakaoApiImageUpload_advc(KakaoVO kakaoVO, Map<String, MultipartFile> files, int fileKeyParam) throws Exception {
// try {
String storePathString = propertyService.getString("Globals.fileStorePath");
File saveFolder = new File(storePathString);
if (!saveFolder.exists()) saveFolder.mkdirs();
// for (MultipartFile file : files.values()) {
MultipartFile file = files.values().stream().findFirst().orElse(null);
if (file == null || file.isEmpty()) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "유효한 이미지 파일이 없습니다.", LocalDateTime.now());
}
String originalName = file.getOriginalFilename();
if (originalName == null || originalName.isEmpty()) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "파일명이 비어 있습니다.", LocalDateTime.now());
}
String ext = FilenameUtils.getExtension(originalName).toLowerCase();
if (!ext.matches("jpg|jpeg|png")) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "지원하지 않는 이미지 형식입니다.");
}
long size = file.getSize();
if (size > 5 * 1024 * 1024) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "이미지 용량은 5MB 이내여야 합니다.");
}
BufferedImage image = ImageIO.read(file.getInputStream());
if (image == null) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "이미지를 읽을 수 없습니다.");
}
int width = image.getWidth();
int height = image.getHeight();
String type = kakaoVO.getImageType();
if ("W".equals(type)) {
if (width != 800 || height != 600) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "와이드 이미지는 800x600 사이즈만 허용됩니다.");
}
} else {
float ratio = width / (float) height;
// log.info("width : [{}], ",width);
// log.info("height : [{}], ",height);
// log.info("ratio : [{}], ",ratio);
if (width < 500 || ratio < 0.75 || ratio > 2.0) {
return new StatusResponse(HttpStatus.BAD_REQUEST, "일반 이미지는 가로 500px 이상, 비율 2:1 이상 또는 3:4 이하만 허용됩니다.");
}
}
String atchFileId = this.saveImgFile(files);
String newName = EgovStringUtil.getTimeStamp() + fileKeyParam;
String filePath = storePathString + File.separator + newName + "." + ext;
file.transferTo(new File(filePath));
// 카카오 API 호출
CloseableHttpClient httpClient = HttpClients.createDefault();
String apiUrl = mjonBizUrl + "/v3/kakao/image/upload";
HttpPost httpPost = new HttpPost(apiUrl);
/*HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", kakaoVO.getImgTitle())
.addTextBody("link", kakaoVO.getImgLink())
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath), ContentType.MULTIPART_FORM_DATA, newName + "." + ext)
.build();
*/
HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addTextBody("imageType", kakaoVO.getImageType())
.addTextBody("title", originalName)
.addTextBody("link", StringUtils.isEmpty(kakaoVO.getImgLink()) ? "https://" : kakaoVO.getImgLink())
.addTextBody("senderKey", kakaoVO.getSenderKey())
.addBinaryBody("image", new File(filePath), ContentType.MULTIPART_FORM_DATA, newName + "." + ext)
.build();
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
JSONParser parser = new JSONParser();
JSONObject object = (JSONObject) parser.parse(result);
String code = object.get("code").toString();
if ("200".equals(code)) {
Map<String, Object> returnMap = new HashMap<>();
returnMap.put("imgUrl", object.get("image").toString());
returnMap.put("fileName", originalName);
returnMap.put("atchFileId", atchFileId);
return new StatusResponse(HttpStatus.OK, "이미지 등록이 완료 되었습니다.", returnMap);
} else {
return new StatusResponse(HttpStatus.BAD_REQUEST, object.get("message").toString(), LocalDateTime.now());
}
} else {
return new StatusResponse(HttpStatus.BAD_REQUEST, "카카오 API 요청 실패", LocalDateTime.now());
}
// }
// } catch (Exception e) {
// log.error("kakaoApiImageUpload_advc API Error", e);
// return new StatusResponse(HttpStatus.BAD_REQUEST, "친구톡 이미지 등록에 실패했습니다.", LocalDateTime.now());
// }
}
private String saveImgFile(Map<String, MultipartFile> files) throws Exception {
String atchFileId = "";
String isThumbFile = "";
String imagePath = "";
String KeyStr = "CANVASIMG_";
Date now = new Date();
SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMdd");
String fdlDate = formatDate.format(now);
imagePath = fileSaveDir+"/file/MMS/" + fdlDate;
if (!files.isEmpty()) {
List<FileVO> result = fileUtil.parseImageFileInf(files, KeyStr, 0, atchFileId, imagePath, isThumbFile);
atchFileId = fileMngService.insertFileInfs(result);
}
return atchFileId;
}
/**
* @Method Name : kakaoApiTemplateImageUpload
* @작성일 : 2023. 2. 16.
* @작성자 : 우영두
* @Method 설명 : 알림톡 이미지 업로드 요청
*/
public Map<String, String> kakaoApiTemplateImageUpload(KakaoVO kakaoVO, Map<String, MultipartFile> files, int fileKeyParam) throws Exception {
Map<String, String> resultMap = new HashMap<String, String>();
try {
int fileKey = fileKeyParam;
String storePathString = propertyService.getString("Globals.fileStorePath");
File saveFolder = new File(storePathString);
if (!saveFolder.exists() || saveFolder.isFile()) {
saveFolder.mkdirs();
}
List<MultipartFile> tmp = new ArrayList<MultipartFile>(files.values());
ListIterator<MultipartFile> itr = tmp.listIterator(tmp.size());
MultipartFile file;
String filePath = "";
FileVO fvo;
File imgFile = null;
String newName = "";
String fileExt = "";
while (itr.hasPrevious()) {
file = itr.previous();
String orginFileName = file.getOriginalFilename();
//--------------------------------------
// 원 파일명이 없는 경우 처리
// (첨부가 되지 않은 input file type)
//--------------------------------------
if ("".equals(orginFileName)) {
continue;
}
////------------------------------------
int index = orginFileName.lastIndexOf(".");
fileExt = orginFileName.substring(index + 1);
newName = EgovStringUtil.getTimeStamp() + fileKey;
long _size = file.getSize();
//이미지 파일 처리라서 확장자까지 모두 붙여서 파일 생성 함
if (!"".equals(orginFileName)) {
filePath = saveFolder + File.separator + newName + "." + fileExt;
file.transferTo(new File(filePath));
File newFile = new File(filePath);
InputStream inputStream = new FileInputStream(newFile);
Image img = new ImageIcon(newFile.toString()).getImage(); // 파일 정보 추출
int orgWidth = img.getWidth(null);
int orgHeight = img.getHeight(null);
long bytes = file.getSize();
long kilobyte = bytes / 1024;
long megabyte = kilobyte / 1024;
//일반이미지, 와이드 이미지 타입별 용량, 크기 체크
String imgType = kakaoVO.getImageType();
/*
*
!기본 이미지
파일규격 : JPG, JPEG, PNG 만 가능/ 용량 최대 500KB
권장 사이즈 : 720px X 720px(가로 500px 미만, 가로:세로 비율이 2:1 미만 또는 3:4 초과 시 업로드 불가)
!와이드 이미지
파일규격 : JPG, JPEG, PNG 만 가능/ 용량 최대 2MB 사이즈 : 800px X 600px
*
* */
//이미지 최대 크기는 500KB를 넘을 수 없다. 실제 498KB여도 500이 넘었다고 등록이 안됨. ㅋ
if(kilobyte > 497) {
resultMap.put("code", "405");
resultMap.put("msg", "파일 최대 용량은 초과하였습니다. 이미지 최대 용량은 500KB를 초과할 수 없습니다.");
return resultMap;
}else if(orgWidth < 500) {//가로 사이즈가 500px 미만이면 안됨
resultMap.put("code", "405");
resultMap.put("msg", "이미지의 최소 가로 사이즈는 500px 이상이어야 합니다.");
return resultMap;
}
//일반 이미지 권장사이즈 초과시 리사이즈 처리 후 저장
int MAX_WIDTH = 800;
int MAX_HEIGHT = 400;
//800 * 400 이 넘으면 리사이징 처리
/*if(orgWidth > 800 || orgHeight > 400) {
orgWidth = MAX_WIDTH;
orgHeight = MAX_HEIGHT;
if (orgWidth > MAX_WIDTH) {
orgHeight = (int) (orgHeight * (MAX_WIDTH / (float) orgWidth));
orgWidth = MAX_WIDTH;
}
if (orgHeight > MAX_HEIGHT) {
orgWidth = (int) (orgWidth * (MAX_HEIGHT / (float) orgHeight));
orgHeight = MAX_HEIGHT;
}
//이미지 리사이징 요청
EgovFileMngUtil fileMngUtil = new EgovFileMngUtil();
BufferedImage resizedImage = fileMngUtil.resize(inputStream ,orgWidth , orgHeight );
//리사이징된 파일 덮어쓰기
ImageIO.write(resizedImage, "jpg", new File(filePath));
}*/
imgFile = new File(filePath);
}
}
if(imgFile.exists()) {//파일이 존재하면 카카오로 전송 처리
//첨부파일 등록 API 전송 요청
String apiUrl = "/v3/kakao/image/alimtalk/template";
String sendUrl = mjonBizUrl+ apiUrl;
String fullFileName = newName + "." + fileExt;
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(sendUrl);
HttpEntity httpEntity = MultipartEntityBuilder.create()
.addTextBody("bizId", mjonBizId)
.addTextBody("apiKey", mjonBizKakaoApiKey)
.addBinaryBody("image", new File(filePath),ContentType.MULTIPART_FORM_DATA,fullFileName)
.build();
httpPost.setEntity(httpEntity);
CloseableHttpResponse response = httpClient.execute(httpPost);
String result = "";
String statusCode = Integer.toString(response.getStatusLine().getStatusCode());
if(statusCode.equals("200")) {
result = EntityUtils.toString(response.getEntity());
result = new String(result.getBytes("iso-8859-1"));//한글 깨짐 현상이 있어서 변환 해줌.
JSONParser parser = new JSONParser();
Object obj = parser.parse(result);
JSONObject object = (JSONObject) obj;
String code = object.get("code").toString();
String msg = object.get("message").toString();
String imgUrl = "";
if(code.equals("200")) {
imgUrl = object.get("image").toString();
}
resultMap.put("code", code);
resultMap.put("msg", msg);
resultMap.put("imgUrl", imgUrl);
}else {
System.out.println("오류 발생");
}
httpClient.close();
}
}catch (Exception e) {
System.out.println("kakaoApiTemplateImageUpload API Error !!! " + e);
resultMap.put("code", "400");
resultMap.put("msg", "알림톡 이미지 등록에 오류가 발생하였습니다.");
resultMap.put("imgUrl", "");
return resultMap;
}
return resultMap;
}
/**
* @throws Exception
* @Method Name : kakaoApiImageDelete
* @작성일 : 2023. 3. 23.
* @작성자 : 우영두
* @Method 설명 : 카카오 친구톡 이미지 삭제 요청
*/
@SuppressWarnings("unchecked")
public KakaoReturnVO kakaoApiImageDelete(KakaoVO kakaoVO) throws Exception {
KakaoReturnVO kakaoReturnVO = new KakaoReturnVO();
try {
String apiUrl = "/v3/kakao/image/delete";
String sendUrl = mjonBizUrl + apiUrl;
JSONObject jsonObject = new JSONObject();
jsonObject.put("bizId", mjonBizId);
jsonObject.put("apiKey", mjonBizKakaoApiKey);
jsonObject.put("imageUrl", kakaoVO.getTemplateImageUrl());
log.info("kakaoVO.getTemplateImageUrl() :: [{}]", kakaoVO.getTemplateImageUrl());
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(sendUrl);
httpPost.setEntity(new StringEntity(jsonObject.toString(), "UTF-8"));
httpPost.addHeader("Content-type", "application/json");
httpPost.addHeader("Accept", "application/json");
HttpResponse response = httpClient.execute(httpPost);
String result = "";
String statusCode = Integer.toString(response.getStatusLine().getStatusCode());
log.info(" + statusCode :: [{}]", statusCode);
if(statusCode.equals("200")) {
result = EntityUtils.toString(response.getEntity());
result = new String(result.getBytes("iso-8859-1"));//한글 깨짐 현상이 있어서 변환 해줌.
System.out.println(result);
JSONParser parser = new JSONParser();
Object obj = parser.parse(result);
JSONObject object = (JSONObject) obj;
String code = object.get("code").toString();
String msg = object.get("message").toString();
kakaoReturnVO.setBizReturnCode(code);
kakaoReturnVO.setBizReturnMsg(msg);
}else {
kakaoReturnVO.setBizReturnMsg("400 : 명령을 실행 오류");
}
} catch (Exception e) {
System.out.println("kakaoApiImageDelete API Error !!! " + e);
kakaoReturnVO.setBizReturnCode("400");
kakaoReturnVO.setBizReturnMsg("친구톡 이미지 삭제에 오류가 발생하였습니다.");
return kakaoReturnVO;
}
return kakaoReturnVO;
}
}