Merge remote-tracking branch 'origin/dev' into dev

main
Kurt92 2 years ago
commit 399aca6412

@ -6,6 +6,8 @@ import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
@ -142,7 +144,38 @@ public class CmmFileDTO {
/**
*
*/
@JsonIgnore
private MultipartFile[] files;
//private List<MultipartFile> files;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Builder
@ToString
public static class PaintwebReq implements Serializable {
private static final long SerialVersionUID = 1L;
private String interfaceSeqN;
private String ctznSttemntDetailSn;
private String fileMastrId;
private String jobSeCode;
private String fileJobId;
private String fileId;
private String orginlFileNm;
private String fileCours;
private String downloadUrl;
private String register;
@JsonIgnore
private MultipartFile file;
//private List<MultipartFile> files;
}
}

@ -120,6 +120,72 @@ public class CmmFileService implements ICmmFileService {
return fileMstDTO;
}
/**
* file
* @param dto
* @param files
* @param isCheckExists
* @return
*/
@Override
public List<CmmFileDTO.FileDtl> saveAddFileDtl(final CmmFileDTO.FileDtl dto, final List<MultipartFile> files,
boolean isCheckExists) {
List<CmmFileDTO.FileDtl> cmmFileDtls = new ArrayList<>();
for(MultipartFile mf : files){
if(!mf.isEmpty()) {
String orgFileName = "";
try {
orgFileName = StringUtils.cleanPath(Objects.requireNonNull(mf.getOriginalFilename()));
CmmFileDTO.FileDtl fileDtlDTO = CmmFileDTO.FileDtl.builder()
.fileMastrId(dto.getFileMastrId())
.fileId(CommUtils.getStringFromUUID())
.fileCours(dto.getFileCours())
.fileCntntsTy(mf.getContentType())
.orginlFileNm(orgFileName)
.fileExtsn(orgFileName.substring(orgFileName.lastIndexOf(".") + 1).toLowerCase())
.fileCpcty(mf.getSize())
.register(getUserUniqId())
.build();
if (StringUtils.hasText(allowExt) && !allowExt.contains(fileDtlDTO.getFileExtsn())) {
log.error("Not support extention :: {}", orgFileName);
//TODO : 에러처리
//return RestError.of(String.format("Not support extention :: %s", orgFileName));
throw BizRuntimeException.create(
MessageKey.CUSTOM_MSG, String.format("Not support extention :: %s", orgFileName));
}
if (fileDtlDTO.getFileCpcty() > (maxSize * 1024)) {
log.error("Over size :: {}[{}]", orgFileName, fileDtlDTO.getFileCpcty());
//TODO : 에러처리
//return RestError.of(String.format("Over size :: %s[%l]", orgFileName, cmmFileDtl.getFileSize()));
throw BizRuntimeException.create(
MessageKey.CUSTOM_MSG, String.format("Over size :: %s[%d]", orgFileName, fileDtlDTO.getFileCpcty()));
}
//동일파일 삭제후 정보 저장
if(isCheckExists) removeExistsUploadFile(fileDtlDTO);
mapper.insertCmmFileDetail(fileDtlDTO);
// 파일 전송
mf.transferTo(new File(this.uploadRoot + dto.getFileCours() + "/" + fileDtlDTO.getFileId()));
cmmFileDtls.add(fileDtlDTO);
// inputStream을 가져와서
// copyOfLocation (저장위치)로 파일을 쓴다.
// copy의 옵션은 기존에 존재하면 REPLACE(대체한다), 오버라이딩 한다
//Files.copy(multipartFile.getInputStream(), copyOfLocation, StandardCopyOption.REPLACE_EXISTING);
}catch(IOException e){
String errMsg = String.format("File Upload Error :: %s", orgFileName);
//TODO : 에러처리
//return RestError.of(String.format("File Upload Error :: %s", orgFileName));
throw BizRuntimeException.create(
MessageKey.CUSTOM_MSG, String.format("File Upload Error :: %s", orgFileName));
}
}
}
return cmmFileDtls;
}
/**
* and

@ -19,6 +19,8 @@ public interface ICmmFileService {
@SuppressWarnings("UnusedReturnValue")
CmmFileDTO.FileMst saveFiles(final CmmFileDTO.FileMst fileMstDTO, final List<MultipartFile> files);
List<CmmFileDTO.FileDtl> saveAddFileDtl(final CmmFileDTO.FileDtl dto, final List<MultipartFile> files,
final boolean isCheckExists);
@SuppressWarnings("UnusedReturnValue")
CmmFileDTO.FileMst saveCtznStmtFiles(final CmmFileDTO.FileMst fileMstDTO, final List<MultipartFile> files, final CmmFileDTO.FileDtl pngFileDtlDto);

@ -35,7 +35,9 @@ import kr.xit.framework.support.util.AjaxMessageMapRenderer;
import kr.xit.framework.support.util.Checks;
import kr.xit.framework.support.util.constants.MessageKey;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping("/framework/biz/cmm/file")
@ -60,6 +62,21 @@ public class CmmFileMgtController {
return mav;
}
@PostMapping(value = "/uploadPaintweb")
public ModelAndView uploadPaintweb(final CmmFileDTO.PaintwebReq dto) {
log.debug("uploadPaintweb >>> {}", dto);
ModelAndView mav = new ModelAndView(FrameworkConstants.JSON_VIEW);
CmmFileDTO.FileDtl cmmFileDtl = CmmFileDTO.FileDtl.builder()
.fileMastrId(dto.getFileMastrId())
.fileCours(dto.getFileCours())
.orginlFileNm(dto.getOrginlFileNm())
.build();
cmmFileService.saveAddFileDtl(cmmFileDtl, Arrays.asList(dto.getFile()), false);
AjaxMessageMapRenderer.success(mav, MessageKey.CMM_INSERT_SUCCESS);
return mav;
}
@GetMapping("/{fileMstId}")
public ModelAndView findFiles(@PathVariable("fileMstId") final String fileMstId) {
if(Checks.isEmpty(fileMstId)) throw BizRuntimeException.create(MessageKey.CUSTOM_MSG, "대상 파일[fileMstId]을 선택해 주세요.");
@ -83,23 +100,6 @@ public class CmmFileMgtController {
return mav;
}
@PostMapping(value = "/uploadPaintweb")//, consumes = "multipart/form-data")
public ModelAndView uploadPaintweb(final CmmFileDTO.Request cmmFileDto, MultipartFile imageFile) {
// if(Checks.isEmpty(cmmFileDto)) throw BizRuntimeException.create(MessageKey.CUSTOM_MSG, "파일 정보가 존재하지 않습니다.");
// if(Checks.isEmpty(cmmFileDto.getJobSeCode())) throw BizRuntimeException.create(MessageKey.CUSTOM_MSG, "파일 구분 코드[fileCtgCd] 정보가 존재하지 않습니다.");
// if(Checks.isEmpty(cmmFileDto.getFileJobId())) throw BizRuntimeException.create(MessageKey.CUSTOM_MSG, "파일 업무 ID[fileBizId] 정보가 존재하지 않습니다.");
ModelAndView mav = new ModelAndView(FrameworkConstants.JSON_VIEW);
CmmFileDTO.FileMst cmmFileMst = CmmFileDTO.FileMst.builder()
.fileMastrId(cmmFileDto.getFileMastrId())
.jobSeCode(cmmFileDto.getJobSeCode())
.fileJobId(cmmFileDto.getFileJobId())
.build();
cmmFileService.saveFiles(cmmFileMst, Arrays.asList(cmmFileDto.getFiles()));
AjaxMessageMapRenderer.success(mav, MessageKey.CMM_INSERT_SUCCESS);
return mav;
}
@PostMapping(value = "/upload2", consumes = "multipart/form-data")
public ModelAndView saveFiles2(final CmmFileDTO.FileMst cmmFileMst, @RequestParam("files") final MultipartFile[] files) {
if(Checks.isEmpty(cmmFileMst)) throw BizRuntimeException.create(MessageKey.CUSTOM_MSG, "파일 정보가 존재하지 않습니다.");

@ -3,7 +3,7 @@
<configuration scan="true" scanPeriod="3600 seconds">
<property name="SLACK_WEBHOOK_URI" source="logging.slack.webhook-uri"/>
<property name="LOG_PATH" value="${user.home}/data/xit/logs"/>
<property name="LOG_PATH" value="${user.home}/data/fims/logs"/>
<property name="LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n"/>
<property name="ROOT_LOG_LEVEL" value="WARN" />
@ -201,7 +201,7 @@
<root level="WARN">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_ROLLING"/>
<!-- <appender-ref ref="ASYNC_ROLLING"/>-->
<!-- <appender-ref ref="ASYNC_ERROR_ROLLING"/>-->
</root>

@ -2,6 +2,20 @@
<%@ include file="/WEB-INF/jsp/framework/taglibs.jsp" %>
<style>
div.draggable {
float: left;
padding: 10px 0 0 20px;
width: 160px;
height: 160px;
background:url(/resources/framework/images/common/clip.png) no-repeat 0 0; */
/*border: 1px solid red;*/
}
div.invert {
background:url(/resources/framework/images/common/clip.png) no-repeat 0 0; */
/*border: 1px solid red;*/
}
</style>
<c:set var="bizName" value="주민 신고 데이타"/>
@ -203,17 +217,33 @@
</c:forEach>
</form>
<div id="ctznImg"></div>
<div style="min-height: 260px">
<img id="uploadImage"/>
<div class="draggable">
<p>title</p>
</div>
<div class="draggable">
<p>
Lorem ipsum dolor<br>
sit amet, consecte<br>turlit.
Aenean
</p>
</div>
<div class="draggable">
<p>Drag me around</p>
</div>
<%-- TODO: id 고정(변경불가)--%>
<div class="draggable" id="imgList" style="display: flex; flex-direction: column; align-items: center"></div>
<div style="min-height: 260px">
<img id="uploadImage"/>
</div>
<div class="popup_btn">
<span class="flr p_flr">
<a href="#" class="btn lightgray" onclick="window.close()">닫기</a>
@ -231,6 +261,7 @@
**************************************************************************/
// let orgData;
var imageEditorPopup = (flag, params) => fnBiz.pagePopup(flag, params);
var callbackReloadImage = () => fnBiz.downloadImg();
/* *******************************
@ -251,6 +282,7 @@
interfaceSeqN: '${reqDTO.interfaceSeqN}',
ctznSttemntDetailSn: '${reqDTO.ctznSttemntDetailSn}'
}
<%-- TODO: id 고정(#ctznImg - 변경불가)--%>
imgDownload(res.data?.contents, '#ctznImg', pr, true);
}
})
@ -297,6 +329,43 @@
$(document).ready(function () {
// orgData = $('form').serialize();
fnBiz.downloadImg();
// $( '#imgList' ).draggable({
// scroll : false,
// containment : 'parent', //부모 요소 안에서만 이동 범위 제한
// handle : '.header' // drag 대상 안 특정 요소에 제한 (여러개 사용 가능)
// });
//$( "#imgList" ).draggable({ revert: true });
//$( "#imgList" ).draggable({ revert: true, helper: "clone" });
$(".draggable").draggable({
cursor:"move",
stack:".draggable",
opacity:0.7,
create : function(event, ui) { //생성시 발생하는 이벤트
console.log("dragcreat event!");
console.log("index:"+$(this).index());
}
});
/*
$(".draggable").bind("dragcreat", function(event, ui) {
console.log("dragcreat event!");
});
*/
$(".draggable").bind("dragstart", function(event, ui) {
console.log("dragstart event!");
$(this).addClass("invert"); //클래스 추가
});
$(".draggable").bind("dragstop", function(event, ui) {
console.log("dragstop event!");
$(this).removeClass("invert"); //클래스 제거
});
$(".draggable").bind("drag", function(event, ui) {
console.log("drags event!");
});
});

@ -11,6 +11,7 @@
<script type="text/javascript" src="/resources/3rd-party/paintweb/html2canvas.min.js"></script>
<script type="text/javascript" src="/resources/3rd-party/paintweb/es6-promise.min.js"></script>
<script type="text/javascript" src="/resources/3rd-party/paintweb/es6-promise.auto.min.js"></script>
<script type="text/javascript" src="/resources/framework/js/cmm/cmmUtil.js"></script>
</head>
<body>
<img id="editableImage"/>
@ -27,25 +28,52 @@
}
const initEditor = () => {
const pw = new PaintWeb();
pw = new PaintWeb();
pw.config.guiPlaceholder = document.getElementById('PaintWebTarget');
pw.config.configFile = 'paintweb-config.json';
pw.config.imageLoad = editImg;
pw.config.imageSaveURL = "/saveImage.do"; // imageSave == image upload
//pw.config.imageSaveURL = "/framework/biz/cmm/file/uploadPaintweb.do"; // imageSave == image upload
//pw.config.imageSaveURL = "/saveImage.do"; // imageSave == image upload
pw.config.imageSaveURL = "/saveImage"; // imageSave == image upload
pw.config.imageDownloadURL = "/fileDownload.do";
//pw.config.afterImageSave = afterImageSave;
pw.config.imageSave = imageSaveTo;
pw.config.afterImageSave = afterImageSave;
pw.init();
}
function imageSaveTo(file, doc, _self){
const {interfaceSeqN, ctznSttemntDetailSn, fileMastrId, fileId, fileCours} = srcImg.dataset;
let formData = new FormData();
formData.append('interfaceSeqN', interfaceSeqN);
formData.append('ctznSttemntDetailSn', ctznSttemntDetailSn);
formData.append('fileMastrId', fileMastrId);
formData.append('fileId', fileId);
formData.append('orginlFileNm', srcImg.name);
formData.append('fileCours', fileCours);
formData.append('file', file);
cmmAjax({
type: 'post',
url: '<c:out value="/framework/biz/cmm/file/uploadPaintweb.do"/>',
processData: false,
contentType: false,
data: formData,
success: (res) => {
window.opener.callbackReloadImage();
window.close();
}
})
return;
}
$(document).ready(function () {
srcImg = window.opener.document.getElementById('<c:out value="${imageTagId}"/>');
editImg = document.getElementById('editableImage');
editImg.src = srcImg.src;
editImg.onload = function () {

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

@ -151,9 +151,9 @@
list-style: none;
margin: 0;
padding: 0;
width: 416px;
/*width: 416px;*/
width:100%;
}
/* .clearfix */
.paintweb_statusbar:after, .paintweb_tools:after, .paintweb_tabsList:after, .paintweb_colormixer_hexalpha:after, .paintweb_main_selection:after {
content: ".";
@ -164,21 +164,24 @@
}
.paintweb_tabPanel_main {
border: 1px solid #9e9e9e;
border-width: 1px 1px 0 1px;
/* border: 1px solid #9e9e9e;
border-width: 1px 1px 0 1px;*/
}
.paintweb_tool, .paintweb_command, .paintweb_icon {
background: #f2f2f2;
border: 1px solid #d6d6d6;
/*background: #f2f2f2;*/
/*border: 1px solid #d6d6d6;*/
}
.paintweb_tools li {
border-top: 0;
border-left: 0;
float: left
float: left;
}
.paintweb_tools li:not(.paintweb_toolSeparator){
border:0px solid red;
padding:10px 8px;
}
.paintweb_tool a, .paintweb_command a, .paintweb_icon a {
background-repeat: no-repeat;
color: #000;
@ -210,7 +213,7 @@
.paintweb_tool.paintweb_disabled a, .paintweb_command.paintweb_disabled a, .paintweb_icon.paintweb_disabled a {
cursor: default;
opacity: 0.4
/*opacity: 0.4*/
}
.paintweb_toolsWrap {
@ -219,12 +222,12 @@
}
.paintweb_toolSeparator {
border: 1px solid #d6d6d6;
/*border: 1px solid #d6d6d6;*/
cursor: default;
float: left;
height: 31px;
overflow: hidden;
width: 31px
width: 31px;
}
.paintweb_statusbar {
@ -304,7 +307,7 @@
.paintweb_main_main,
.paintweb_main_selection,
.paintweb_main_shadow,
.paintweb_main_text { margin: 5px }
.paintweb_main_text { /*margin: 5px*/ }
.paintweb_opt_lineWidth, .paintweb_opt_miterLimit {
background: #f2f2f2;
@ -497,7 +500,8 @@
.paintweb_main_selection .paintweb_command {
float: left;
margin: 0;
padding: 0
padding: 0;
padding:6px;
}
.paintweb_main_selection .paintweb_cmd_selectionCopy,
@ -514,21 +518,21 @@
}
.paintweb_opt_selectionTransparent, .paintweb_opt_selectionTransform {
background: #f2f2f2;
border: 1px solid #d6d6d6;
left: 110px;
/*background: #f2f2f2;*/
/*border: 1px solid #d6d6d6;*/
left: 150px;
line-height: 31px;
margin: 0;
padding: 0 5px;
position: absolute;
top: 0;
top: 10px;
vertical-align: middle;
width: 15em
width: 15em;
}
.paintweb_opt_selectionTransform {
border-top: 0;
top: 33px
top: 40px
}
.paintweb_opt_fontFamily label, .paintweb_opt_fontSize label { display: none }
@ -955,25 +959,25 @@
/* Icons */
.paintweb_cmd_historyUndo a { background-image: url('icons/historyUndo.png') }
.paintweb_cmd_historyUndo a { background-image: url('icons/i_cancel.png') }
.paintweb_cmd_historyRedo a { background-image: url('icons/historyRedo.png') }
.paintweb_cmd_historyRedo a { background-image: url('icons/i_replay.png') }
.paintweb_cmd_selectionCut a { background-image: url('icons/selectionCut.png') }
.paintweb_cmd_selectionCut a { background-image: url('icons/i_cut.png') }
.paintweb_cmd_selectionCopy a { background-image: url('icons/selectionCopy.png') }
.paintweb_cmd_selectionCopy a { background-image: url('icons/i_copy.png') }
.paintweb_cmd_clipboardPaste a { background-image: url('icons/clipboardPaste.png') }
.paintweb_cmd_clipboardPaste a { background-image: url('icons/i_paste.png') }
.paintweb_cmd_selectionCrop a { background-image: url('icons/selectionCrop.png') }
.paintweb_cmd_selectionCrop a { background-image: url('icons/i_crop.png') }
.paintweb_cmd_selectionDelete a { background-image: url('icons/selectionDelete.png') }
.paintweb_cmd_selectionDelete a { background-image: url('icons/i_block.png') }
.paintweb_cmd_selectionFill a { background-image: url('icons/selectionFill.png') }
.paintweb_cmd_selectionFill a { background-image: url('icons/i_colorfill.png') }
.paintweb_cmd_imageSave a { background-image: url('icons/imageSave.png') }
.paintweb_cmd_imageSave a { background-image: url('icons/i_save.png') }
.paintweb_cmd_imageRotate a { background-image: url('icons/imageRotate.png') }
.paintweb_cmd_imageRotate a { background-image: url('icons/i_rotation.png') }
.paintweb_cmd_imageClear a { background-image: url('icons/imageClear.png') }
@ -998,13 +1002,13 @@
.paintweb_tool_pencil a { background-image: url('icons/pencil.png') }
.paintweb_tool_hand a { background-image: url('icons/hand.png') }
.paintweb_tool_hand a { background-image: url('icons/i_pinch.png') }
.paintweb_tool_polygon a { background-image: url('icons/polygon.png') }
.paintweb_tool_rectangle a { background-image: url('icons/rectangle.png') }
.paintweb_tool_selection a { background-image: url('icons/selection.png') }
.paintweb_tool_selection a { background-image: url('icons/i_select.png') }
.paintweb_tool_text a { background-image: url('icons/text.png') }

@ -2557,7 +2557,7 @@ function PaintWeb (win, doc) {
*
* @returns {Boolean} True if the operation was successful, or false if not.
*/
this.imageSave = function (type) {
this.imageSave = async function (type) {
var canvas = _self.layer.canvas,
cfg = _self.config,
img = _self.image,
@ -2568,8 +2568,9 @@ function PaintWeb (win, doc) {
return false;
}
var extMap = {'jpg' : 'image/jpeg', 'jpeg' : 'image/jpeg', 'png'
: 'image/png', 'gif' : 'image/gif'};
var extMap = {
'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'gif': 'image/gif'
};
// Detect the MIME type of the image currently loaded.
if (typeof type !== 'string' || !type) {
@ -2588,18 +2589,18 @@ function PaintWeb (win, doc) {
// We consider that other formats than PNG do not support transparencies.
// Thus, we create a new Canvas element for which we set the configured
// background color, and we render the image onto it.
if (type !== 'image/png' || img.zoom!=1) {
if (type !== 'image/png' || img.zoom != 1) {
canvas = doc.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = img.width * img.zoom;
canvas.height = img.height * img.zoom;
canvas.width = img.width * img.zoom;
canvas.height = img.height * img.zoom;
context.fillStyle = cfg.backgroundColor;
context.fillRect(0, 0, img.width, img.height);
context.drawImage(_self.layer.canvas, 0, 0, canvas.width, canvas.height);
context = null;
context = null;
}
try {
@ -2616,21 +2617,50 @@ function PaintWeb (win, doc) {
}
canvas = null;
// alert('idata~~~'+idata)
if (!idata || idata === 'data:,') {
//alert('idata~~~'+idata)
return false;
}
// by gujc
if (!_self.config.imageSaveURL) {
if (_self.config.afterImageSave) _self.config.afterImageSave();
return;
// TODO: save image
//--------------------------------------------------------------------
// 변경된 부분
//--------------------------------------------------------------------
if (!_self.config.imageSave) {
if (_self.config.afterImageSave) _self.config.afterImageSave();
return;
}
let fileType = 'image/';
const regx = new RegExp('.(gif|jpg|jpeg|tiff|png|ico)$', 'i')
let name = (/[^(/|\\)]*$/).exec(idata)[0]
// 20220915_5df30439017240afbc7081ae9bfbfa2f 와 같은 형태인 경우 imageName으로
if(!regx.exec(name)){
name = srcImg.name;
}
fileType += regx.test(name) ? regx.exec(name)[0].replace('.', '') : 'jpg'
// mine type 'jpg' > jpeg로 변경
fileType = fileType.replace('image/jpg', 'image/jpeg');
const bstr = atob(idata.split(",")[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while(n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const file = new File([u8arr], name, {type:fileType});
//alert(`fileCpcty=${srcImg.dataset.fileCpcty},fileSize=${file.size}`)
_self.config.imageSave(file, img.width, img.height, doc, _self);
imageSaveTo(idata, img.width, img.height);
return;
//---------------------------------------------------------------------
var ev = new appEvent.imageSave(idata, img.width, img.height),
cancel = _self.events.dispatch(ev);
@ -2638,78 +2668,37 @@ function PaintWeb (win, doc) {
return true;
}
/*
var imgwin = _self.win.open();
if (!imgwin) {
return false;
}
imgwin.location = idata;
*/
/*
var imgwin = _self.win.open();
if (!imgwin) {
return false;
}
imgwin.document.write('<iframe src="' + idata + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>');
*/
/*
var iframe = "<iframe width='100%' height='100%' src='" + idata + "'></iframe>";
var x = window.open();
x.document.open();
x.document.write(iframe);
x.document.close();
*/
idata = null;
_self.events.dispatch(new appEvent.imageSaveResult(true));
return true;
};
function imageSaveTo(idata, width, height){
var ex = /\?filename=([a-z0-9\-]+)\&?/i;
var dashdash = '--';
var crlf = '\r\n';
var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var progressBar = doc.createElement("div");
progressBar.style.left = ((w-200)/2) + "px";
progressBar.className = "progressBar";
document.body.appendChild(progressBar);
var progressRate = doc.createElement("div");
progressRate.innerText = "Saving";
progressRate.className = "progressRate";
progressBar.appendChild(progressRate);
var url = srcImg.src;
const map = new Map(Object.entries(srcImg.dataset));
let pr = '';
map.forEach((v,k)=>{
//pr += ` ${k}="${v}";`;
pr += ` name="${k}"${crlf}${crlf}${v};`;
})
var filename = url.match(ex)[1];
var boundary = 'multipartformboundary' + (new Date).getTime();
var xhr = new XMLHttpRequest();
xhr.open("POST", _self.config.imageSaveURL);
xhr.setRequestHeader('content-type', 'multipart/form-data; boundary='+ boundary);
var builder = dashdash + boundary + crlf + 'Content-Disposition: form-data; name="imageFile"' +
'; filename="' + filename + '";' + crlf + ' Content-Type: application/octet-stream' + crlf + crlf;
// '; filename="' + filename + '";' + pr + crlf + ' Content-Type: application/octet-stream' + crlf + crlf;
builder += idata;
builder += crlf + dashdash + boundary + crlf + 'Content-Disposition: form-data; name="filename"' + crlf + crlf + filename;
//builder += crlf + dashdash + boundary + crlf + 'Content-Disposition: form-data; name="filename"' + crlf + crlf + filename + pr;
builder += crlf + dashdash + boundary + dashdash + crlf;
xhr.onload = function () {
var newImg = document.createElement("IMG");
newImg.onload = function () {
srcImg.src = newImg.src + "#img" + (new Date()).getTime();
if (_self.config.afterImageSave) _self.config.afterImageSave();
}
newImg.src = _self.config.imageDownloadURL + "?filename=" + filename+ "#img" + (new Date()).getTime();
};
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
var p = evt.loaded / evt.total * 100;
progressRate.style.width = p + "%";
progressRate.innerText = progressRate.style.width;
if (p==100) {
progressRate.innerText = "Saved";
}
}
}, false);
xhr.send(builder);
}
/**
* image rotation. add by gujc.
*/
@ -3032,4 +3021,3 @@ PaintWeb.baseFolder = '';
})();
// vim:set spell spl=en fo=wan1croqlt tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:

@ -219,6 +219,7 @@ const cmmAjax = (param) => {
,data: param.data
,async: nvl(param.async, true)
,dataType: nvl(param.dataType, "json")
,processData: nvl(param.processData, true)
,contentType: nvl(param.contentType, 'application/x-www-form-urlencoded;charset=UTF-8')
,cache : false
,beforeSend: (jqXhr, settings) => {

@ -6,27 +6,46 @@
* 이미지 url 사용
* @param {object} cmmFileDtls
* @param {string} appendElementId - '#ctznImg'
* @param {object} stmtDtlDTO - 시민신고상세정보
* @param {object} reqDTO - 시민신고상세 PK
* </pre>
*/
function imgDownload(cmmFileDtls, appendElementId, reqDTO, isEditor) {
const downloadUrl = '/framework/biz/cmm/file/download.do';
/*
<div id="imgList">
<div id="ctznImg"></div>
</div>
*/
let imgEl = document.querySelector(appendElementId);
if(imgEl?.hasChildNodes()){
imgEl.parentNode.removeChild(imgEl);
}
imgEl = document.createElement("div");
//TODO: id 고정(#ctznImg - 변경불가)
imgEl.setAttribute("id", 'ctznImg');
cmmFileDtls.forEach((dtl, idx) => {
const params = "?filename=" +dtl.orginlFileNm+ $.param(dtl);
//const params = "?filename=" +dtl.orginlFileNm + $.param(dtl);
const params = "?filename=" + $.param(dtl);
const title = reqDTO ? dtl.orginlFileNm+'['+reqDTO.ctznSttemntDetailSn+']' : dtl.orginlFileNm;
const x = document.createElement("img");
x.setAttribute("src", downloadUrl+params);
x.setAttribute("id", dtl.fileId);
//x.style = 'width:150px; display: block;';
x.style = 'height:300px;';
//x.setAttribute("width", "304");
//x.setAttribute("height", "228");
x.style = 'width:150px;';
x.style = 'height:150px;';
//x.setAttribute("object-fit", "cover");
//x.setAttribute("object-fit", "scale-down");
x.setAttribute("title", title);
x.setAttribute("alt", dtl.orginlFileNm);
x.setAttribute("name", dtl.orginlFileNm);
x.setAttribute("data-file-mastr-id", dtl.fileMastrId);
x.setAttribute("data-file-id", dtl.fileId);
x.setAttribute("data-file-cours", dtl.fileCours);
x.setAttribute("data-file-cpcty", dtl.fileCpcty);
if(reqDTO) {
x.setAttribute("data-interface-seq-n", reqDTO.interfaceSeqN);
x.setAttribute("data-ctzn-sttemnt-detail-sn", reqDTO.ctznSttemntDetailSn);
@ -40,11 +59,11 @@ function imgDownload(cmmFileDtls, appendElementId, reqDTO, isEditor) {
fnBiz.pagePopup('imageView', dtl);
}
})
document.querySelector(appendElementId).appendChild(x);
imgEl.appendChild(x);
document.querySelector('#imgList').appendChild(imgEl);
})
}
/**
* <pre>
* 첨부파일 정보 목록으로 부터 이미지 download
@ -80,7 +99,6 @@ function imgDownload2(cmmFileDtls, appendElementId, dtlSeq) {
x.setAttribute("alt", dtl.orginlFileNm);
//x.setAttribute("id", dtl.fileMastrId);
x.setAttribute("name", dtl.orginlFileNm);
x.setAttribute("fileMastrId", dtl.fileMastrId);
x.setAttribute("ctznSttemntDetailSn", dtlSeq);
x.addEventListener('click', (e)=>{
$('#uploadImage').attr("src", url);

@ -508,7 +508,7 @@ function serialize (formData) {
* </pre>
*/
function downloadImage(img, fileName) {
var imgData = atob(img.src.split(',')[1]),
var imgData = atob(img.split(',')[1]),
len = imgData.length,
buf = new ArrayBuffer(len),
view = new Uint8Array(buf),
@ -529,8 +529,8 @@ function downloadImage(img, fileName) {
//var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.style = 'display: none';
//a.href = url;
a.href = img.src;
a.href = URL.createObjectURL(blob);;
//a.href = img.src;
a.download = fileName;
document.body.appendChild(a);
a.click();
@ -541,3 +541,140 @@ function downloadImage(img, fileName) {
}, 100);
}
}
var readBlob = async () => {
const data = await fetch('https://play-lh.googleusercontent.com/hYdIazwJBlPhmN74Yz3m_jU9nA6t02U7ZARfKunt6dauUAB6O3nLHp0v5ypisNt9OJk');
const blob = await data.blob();
const reader = new FileReader();
reader.onload = () => {
const base64data = reader.result;
console.log(base64data)
}
reader.readAsDataURL(blob);
fetch('https://www.business2community.com/wp-content/uploads/2014/04/Free.jpg')
.then((response) => response.blob())
.then((blob) => {
const url = URL.createObjectURL(blob);
document.querySelector('img').src = url;
document.querySelector('a').href = url;
});
}
/**
*
* @param b64Data
* @param contentType
* @param sliceSize
* @returns {Blob}
*/
// bas64를 blob으로 변환해주는 함수
function b64toBlob(b64Data, contentType = '', sliceSize = 512) {
const image_data = atob(b64Data.split(',')[1]); // data:image/gif;base64 필요없으니 떼주고, base64 인코딩을 풀어준다
const arraybuffer = new ArrayBuffer(image_data.length);
const view = new Uint8Array(arraybuffer);
for (let i = 0; i < image_data.length; i++) {
view[i] = image_data.charCodeAt(i) & 0xff;
// charCodeAt() 메서드는 주어진 인덱스에 대한 UTF-16 코드를 나타내는 0부터 65535 사이의 정수를 반환
// 비트연산자 & 와 0xff(255) 값은 숫자를 양수로 표현하기 위한 설정
}
return new Blob([arraybuffer], { type: contentType });
/*
const contentType = 'image/png';
const b64Data =
'data:image/gif;base64,R0lGODlhAAEAAcQAALe9v9ve3/b393mDiJScoO3u74KMkMnNz4uUmKatsOTm552kqK+1uNLW18DFx3B7gP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE5QjEwQjYyNTc4MkUxRURBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjEzN0VEMDZBQjMyNzExRTE4REMzRUZGMkFCOTM1NkZBIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjEzN0VEMDY5QjMyNzExRTE4REMzRUZGMkFCOTM1NkZBIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDI4MDExNzQwNzIwNjgxMTlCMTBCNjI1NzgyRTFFREEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTlCMTBCNjI1Nzgy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';
const blob = b64toBlob(b64Data, contentType); // base64 -> blob
const blobUrl = URL.createObjectURL(blob); // object url 생성
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
*/
}
/**
* 전달받은 이미지를 base64로 인코딩한다
* @param file - 이미지 파일 또는 이미지 URL
* @param maxWidth - 인코딩 시의 이미지 max width 사이즈
* @returns {Promise<any>}
*/
var readImage = () => {
let image = this.$refs.image.src
this.toBlob(image)
.then(res => {
console.log(res)
this.image = {
filename: res.name,
size: res.size,
type: res.type,
lastModified: res.lastModified
}
})
};
/**
* 이미지 url을 blob 파일로 변환하여 전달한다
* @param url
* @returns {Promise<any>}
*/
var toBlob = (url) => {
return new Promise((resolve, reject) => {
this.base64Encode(url)
.then(res => {
let byteString = atob(res.dataUrl)
let ab = new ArrayBuffer(byteString.length)
let ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
// write the array buffer to blob
let blob = new Blob([ab], {type: 'image/' + res.type})
let formData = new FormData()
formData.append('file', blob, res.name)
resolve(formData.get('file'))
})
})
};
/**
* 전달받은 이미지를 base64로 인코딩한다
*/
var base64Encode = (url) => {
const re = new RegExp('.(gif|jpg|jpeg|tiff|png|ico)$', 'i')
let name = (/[^(/|\\)]*$/).exec(url)[0]
let type = re.test(name) ? re.exec(name)[0].replace('.', '') : 'jpg'
return new Promise((resolve, reject) => {
let image = new Image()
image.onload = function (event) {
let canvas = document.createElement('canvas')
// draw canvas
canvas.width = image.naturalWidth
canvas.height = image.naturalHeight
canvas.getContext('2d').drawImage(image, 0, 0)
let dataUrl = canvas.toDataURL('image/' + type)
resolve({
name: name,
type: type,
dataUrl: dataUrl.split(',')[1]
})
}
image.onerror = function () {
let msg = `"${file}"을 로딩하는 데 오류가 발생하였습니다. 이미지 파일을 확인해주세요.`
alert(msg)
console.error(msg)
}
image.crossOrigin = 'anonymous';
image.src = url
})
}

Loading…
Cancel
Save