Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- terraform
- 체코
- JenkinsFile
- 三井住友カード
- 태국
- vba
- 熱海
- documentdb
- Selenium
- pyenv
- 메르페이
- 釜つる
- javascript
- 카마츠루
- node.js
- 프라하
- duckdb
- CSV
- local
- codebuild
- PayPay
- Python
- typescript
- PostgreSQL
- 미츠이 스미토모
- 페이페이
- react.js
- 방콕
- 뮌헨
- 아타미
Archives
- Today
- Total
도쿄사는 외노자
React.js에서의 PDF파일의 DB저장과 열람 본문
일단 화면은 이런 식.
Modal을 열 때, 해당 데이터의 컨디션에 따라 업로드/열람 버튼을 구분하여 출력한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | var React = require('react'); var basic = require('../../../basic'); var DatePicker = require('../../datepicker'); var Header = React.createClass({ render: function() { return ( // ... ); } }); var PdfButton = React.createClass({ render: function() { if(this.props.data.interview_pdf && (this.props.data.status=="interviewed")) { return ( <button type='button' className='btn btn-warning btnPdfDownload center-block'>면담결과 열람</button> ) } return ( <button type='button' className='btn btn-warning btnPdfUpload center-block'>면담결과 업로드</button> ) } }); var Body = React.createClass({ render: function() { var iframeStyle = { width: '100%', height: '700px' } return ( <div className='modal-body'> <div className='box-body'> <div className='form-horizontal'> <div className='form-group'> <label htmlFor='inputInterviewDate' className='col-sm-2 control-label'>면담일</label> <div className='col-sm-10'> <DatePicker.Simple id='inputInterviewDate' placeholder='YYYY-MM-DD' value={this.props.data.interview_date} /> </div> </div> <div className='form-group'> <label htmlFor='inputInterviewNote' className='col-sm-2 control-label'>비고</label> <div className='col-sm-10'> <textarea className='form-control' id='inputInterviewNote' rows="3"></textarea> </div> </div> <div className='form-group'> <div id="pdfFileName" className="span12 text-center"><label></label></div> <PdfButton data={this.props.data} /> <input id="inputPdfFile" type="file" style={{display: 'none'}} /> </div> </div> </div> </div> ); } }); var Footer = React.createClass({ render: function() { return ( // ... ) } }); var Modal = React.createClass({ getDefaultProps: function() { return { id: 'modal-id', header: { title: 면담결과Modal } } }, render: function() { return ( <div id={this.props.id} className='modal fade' tabIndex='-1' role='dialog'> <div className='modal-dialog'> <div className='modal-content' data-user={JSON.stringify(this.props.content_value)}> <Header data={this.props.header} /> <Body data={this.props.content_value} /> <Footer data={this.props.is_update} /> </div> </div> </div> ); } }); module.exports = { Header: Header, Body: Body, Footer: Footer, Modal: Modal } | cs |
Modal을 열 때, parameter를 전부 JSON.stringify를 사용해 div.modal-content에 때려박아 두었다.
input type file은 별로 이쁘지 않으니, 따로 버튼을 만들어, trigger를 걸어놓는 것으로 하였다.
1 2 3 4 5 6 7 8 | // PDF파일 업로드 버튼 $('#' + param.id + ' .btnPdfUpload').off('click').on('click', function(e) { e.preventDefault(); e.stopPropagation(); var $target = $(e.target); $target.siblings('input#inputPdfFile').trigger('click'); }); | cs |
하여, trigger로 파일 입력 버튼을 기동하면 파일 선택 창이 열림.
여기서 업로드 할 파일을 선택하여, onChange가 발동했다면 다음 동작을 실행.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // file select $('#' + param.id + ' input#inputPdfFile').change(function(e) { e.preventDefault(); e.stopPropagation(); var selectedFile = $(this)[0].files; var param = { file: selectedFile[0], target: $(e.target) } Promise.resolve(param) .then(validatePdf) .then(setPdfFile) .then(resolve) .catch(reject) ; }); | cs |
선택된 파일에 대한 validate를 실행.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | function validatePdf(param) { return new Promise(function(resolve, reject) { var errors = 0; // 브라우저 호환 확인 if (!window.FileReader) { errors = errors+1; notice.error(basic.i18n.get('App.validate.notFitBrowser')); } // 파일이 존재하는지 확인 if (!param.file) { errors = errors+1; noice.error(basic.i18n.get('App.validate.notExistFile')); } // 파일 사이즈 확인 if (param.file.size==0) { errors = errors+1; notice.error(basic.i18n.get('App.validate.emptyFile')); } // 확장자가 PDF가 맞는지 확인 var fileName = param.file.name.split('.'); if (fileName[fileName.length-1] != 'pdf' && (fileName[fileName.length-1] != "PDF")) { errors = errors+1; notice.error(basic.i18n.get('App.validate.notPdfFile')); } if (errors > 0) { reject(param); }else{ resolve(param); } }); } | cs |
validate를 통과했다면, pdf를 base64로 변환하여 div#pdfFileName에 attr로 박아둔다.
이후 저장 버튼을 눌러, 다른 입력값과 함께 DB에 저장.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function setPdfFile(param) { return new Promise(function(resolve, reject) { param.target.siblings('div#pdfFileName').text(param.file.name); var fileReader = new FileReader(); var base64; fileReader.onload = function(fileLoadedEvent) { base64 = fileLoadedEvent.target.result; param.target.siblings('div#pdfFileName').attr("data-pdffile", base64); }; fileReader.readAsDataURL(param.file); resolve(param); }); } | cs |
이미 PDF가 업로드 되었으며, 데이터 컨디션이 interviewed인 데이터일 경우는,
면담결과 업로드 버튼 대신 면담결과 열람 버튼이 나온다.
이 경우는 이미 div.modal-content에 해당 PDF가 base64의 형태로 들어가 있으니,
그걸 따와서 pdf로 변환하기만 하면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 | // 면담결과 열람 버튼 $('#' + param.id + ' .btnPdfDownload').off('click').on('click', function(e){ e.preventDefault(); e.stopPropagation(); var $target = $(e.target); var user = $target.closest('div.modal-content').data('user'); var base64EncodedPDF = user.interview_pdf; if (base64EncodedPDF && base64EncodedPDF.length>0) { window.open(encodeURI(base64EncodedPDF)); } }); | cs |
변환 후, 새 탭에서 해당 PDF를 출력하도록 하는 것으로 완료.
'Tech > React.js' 카테고리의 다른 글
라벨의 Byte Length에 따른 요소 길이 조정 (0) | 2017.01.23 |
---|---|
React.js에서의 propTypes 복수 지정 (0) | 2017.01.12 |
CSV Download Button (0) | 2016.12.19 |
React.js에서의 modal의 cache삭제 (0) | 2016.11.04 |
HTML5 input type number에서의 maxlength 적용 (0) | 2016.09.21 |