외부 이미지 복붙 -> 바로 파일 첨부에 관해 고민을 하고 있는데요.
애드온보다는 코어 위시 리스트에 있는 기능이라는 언급이 있어서
일단 (감히 코어를 건드릴 깜냥은 못돼서ㅜ) 애드온으로 디벨롭해보고 있습니다.
특히 @기진곰님의 이미지 자동 첨부 애드온의 소스를 활용했습니다 :)
현재 다음과 같은 구조인데요.
사실 procFileUpload인가 하는 함수를 exec_json으로 처리하면 간단할 것 같은데, 이게 외부이미지 파일 첨부 때문에 쉽지가 않더라구요. 그래서 복잡ㅜ
암튼 현재까지 파일 첨부는 잘 되고 있습니다 :D
- CK에디터가 로드됐을 때, paste 이벤트를 걸어줌.
- paste된 내용 중에 이미지 태그가 있으면 ajax로 서버와 통신.
- 서버단에서는 캐시를 이용해 전달된 문서/댓글 srl과 이미지 url을 기준으로 선별적으로 파일 첨부(insertFile 함수 실행)를 진행.
- 서버에서 다시 스크립트쪽으로 img src에 들어갈 첨부파일 경로를 전달
- 스크립트에서는 1) 에디터의 첨부파일 리스트를 리로드하고, 2) paste 내용에서 기존 img src를 서버쪽 첨부파일의 src로 바꿔치기
아직 정리는 덜 됐지만ㅎ 현재 작업한 소스는 대강 다음과 같습니다.
현재까지 제가 발견한 문제는 이렇습니다.
1) 일단 img 태그 식별할 때 외부이미지인지, 서버쪽 이미지인지 분간이 안 되고 있네요ㅜ
2) 이미지 자동 첨부 애드온에 있는 gif 처리 방식도 있으면 좋을 것 같고
3) 이미지 복붙으로 파일을 첨부하는 동안 로딩 이미지도 있으면 좋겠구요.
고려사항이 더 있거나 하면 알려주시면 감사하겠습니다~
jQuery(document).ready(function($) { var editor = $('[data-editor-primary-key-name$="_srl"]'); if ( editor.length < 1 ) { return; } var paste = ''; var matches = []; var editor_sequence = editor.data('editor-sequence'); var editor_target = editor.data('editor-primary-key-name'); var upload_target_srl = $('[name="'+ editor_target +'"]').val(); var img_url_list = [], img_src_list = []; var is_image = /<img [^>]*src="[^"]*"[^>]*>/gm; setTimeout(function() { var ck_editor = CKEDITOR.instances.editor1; ck_editor.on('paste', function(e) { paste = e.data.dataValue; matches = paste.match(is_image); if ( matches ) { img_url_list = matches.map(x => x.replace(/.*src="([^"]*)".*/, '$1')); var params = { mid: current_mid, image_urls: img_url_list.join(','), editor_sequence: editor_sequence, upload_target_srl: upload_target_srl } $.ajax({ url: 서버쪽 php 파일, dataType: 'json', data: params, async: false, success: function(data) { $container.data('instance').loadFilelist($container); img_src_list = data; }, complete: function() { $.map(img_url_list, function(v, i) { paste = paste.replace(v, img_src_list[i]); }); }, error: function(x,e) { if ( x.status == 0 ) { alert('네트워크 연결 상태를 체크해주세요.'); } else if ( x.status == 404 ) { alert('요청받은 URL을 찾을 수 없습니다.'); } else if ( x.status == 500 ) { alert('내부 서버 오류 : 관리자에게 문의해보세요.'); } else if ( e == 'parsererror' ) { alert('요청받은 내용을 변환하는 실패했습니다.'); } else if ( e == 'timeout' ) { alert('연결 시간이 초과했습니다.'); } else { alert('알 수 없는 에러가 발생했습니다.\n' + x.responseText); } } }); e.data.dataValue = paste; } else { return false; } }); }, 1200); });
<?php /** * @Most Parts of this code below are brought from * @https://github.com/poesis/xe-autoattach/blob/master/autoattach.class.php * @author Kijin Sung <[email protected]> * @license GPLv2 or Later <https://www.gnu.org/licenses/gpl-2.0.html> * * @The Original source is described like this : * This addon automatically finds unattached images in documents and comments * and converts them into real attachments. This can be useful because * many users cannot distinguish between external images and real attachments, * but the website administrator must be careful because self-hosting all * images may result in copyright infringement. */ include '../../common/autoload.php'; Context::init(); $image_url_list = explode(',', $_REQUEST['image_urls']); $editor_sequence = (int)$_REQUEST['editor_sequence']; // Get upload_target_srl $upload_target_srl = (int)$_REQUEST['upload_target_srl'] ?: 0; if (!$upload_target_srl) { $upload_target_srl = $_SESSION['upload_info'][$editor_sequence]->upload_target_srl; } if (!$upload_target_srl) { $upload_target_srl = getNextSequence(); $_SESSION['upload_info'][$editor_sequence]->upload_target_srl = $upload_target_srl; } $logged_info = Context::get('logged_info'); $module_srl = ModuleModel::getModuleInfoByMid($_REQUEST['mid'])->module_srl; $module_config = FileModel::getFileConfig($module_srl); $file_info = array(); $response = array(); foreach ( $image_url_list as $key => $image_url ) { // If the same image has already been downloaded, reuse the cached version. $cache_key = 'url_cache:' . getNumberingPath($upload_target_srl) . $image_url; if ( Rhymix\Framework\Cache::get($cache_key) ) { $uploaded_filename = Rhymix\Framework\Cache::get($cache_key); $response[$key] = str_replace('/addons/youtube_converter', '', htmlspecialchars($uploaded_filename)); continue; } // Attempt to download the image. $temp_path = _XE_PATH_ . 'files/cache/youtube_converter/' . md5($image_url . microtime() . mt_rand()); $download_start_time = microtime(true); $image_timeout = 4; $redirect_settings = array('follow_redirects' => true, 'max_redirects' => 2); $status = FileHandler::getRemoteFile(urldecode($image_url), $temp_path, null, $image_timeout, 'GET', null, array(), array(), array(), $redirect_settings); clearstatcache($temp_path); if (!$status || !file_exists($temp_path) || !filesize($temp_path)) { FileHandler::removeFile($temp_path); continue; } // Check the current module's attachment size limit. if ($module_config->allowed_filesize && ($_SERVER['REQUEST_METHOD'] === 'GET' || $logged_info->is_admin !== 'Y')) { if (filesize($temp_path) > $module_config->allowed_filesize * 1024 * 1024) { FileHandler::removeFile($temp_path); continue; } } if ($module_config->allowed_attach_size && ($_SERVER['REQUEST_METHOD'] === 'GET' || $logged_info->is_admin !== 'Y')) { $total_size = executeQuery('file.getAttachedFileSize', (object)array('upload_target_srl' => $upload_target_srl)); if($total_size->data->attached_size + filesize($temp_path) > $module_config->allowed_attach_size * 1024 * 1024) { FileHandler::removeFile($temp_path); continue; } } // Guess the correct filename and extension. if (preg_match('@[^\\\\/\\?=]+\.(gif|jpe?g|png|bmp|svg)\b@i', urldecode($image_url), $matches)) { $temp_name = $matches[0]; } else { $temp_name = md5($image_url . microtime() . mt_rand()); } if (preg_match('/^[0-9a-f]{32}$/', $temp_name)) { $image_info = @getimagesize($temp_path); if (!$image_info) $temp_ext = 'jpg'; switch ($image_info['mime']) { case 'image/gif': $temp_ext = 'gif'; case 'image/jpeg': $temp_ext = 'jpg'; case 'image/png': $temp_ext = 'png'; case 'image/x-ms-bmp': $temp_ext = 'bmp'; default: $temp_ext = 'jpg'; } $temp_name .= '.' . $temp_ext; } $file_info['name'] = $temp_name; $file_info['tmp_name'] = $temp_path; // Register as attachment. $oFile = getController('file')->insertFile($file_info, $module_srl, $upload_target_srl, 0, true); FileHandler::removeFile($temp_path); if (!$oFile) { continue; } Rhymix\Framework\Cache::set($cache_key, $oFile->get('uploaded_filename'), 3600 * 24 * 30); // Create the response if ($oFile->get('direct_download') === 'Y') { $response[$key] = str_replace('/addons/youtube_converter', '', FileModel::getDirectFileUrl($oFile->get('uploaded_filename'))); } else { $response[$key] = str_replace('/addons/youtube_converter', '', FileModel::getDownloadUrl($oFile->get('file_srl'), $oFile->get('sid'), $module_srl)); } } echo json_encode($response); Context::close(); ?>
에디터자동완성모듈 에서도
1)내.외부 이미지 구분 없이 작동 합니다.
-클립보드에 순수한 이미지정보만 있지 않을까요?
3)첨부가 워낙 순식간이어서 에디터 하단에 첨부 부분에 첨부된게 보여서 어색하거나 첨부가 되는지 모르지는 않는거 같습니다.