Translate
2017년 10월 27일 금요일
[IntelliJ] CSV 파일을 테이블 형식으로 보면서 편집하자.
CSV 파일 사용할일이 종종 있는데,,
IntelliJ 에서 편하게 볼 수 있는 방법이 없을까 하고 알아보니 기본 기능에 포함이 되어 있었다.
아래와 같이 사용이 가능하다.
1. CSV 파일을 열면 기본적으로 아래와 같이 보여지게 된다.
1004lucifer
2. Edit > Edit as Table 선택
3. 아래와 같이 설정화면이 나오는데 그냥 OK를 누르던가 설정을 변경하면 된다.
(나의 경우엔 세미콜론으로 구분하기위해 포멧을 하나 더 만들었다.)
1004lucifer
4. 아래와 같이 화면이 변경된다.
(하단에 Text / Data 구분하여 볼 수 있는 탭이 생긴다.)
참고
- https://www.jetbrains.com/help/idea/edit-as-table-file-name-format-dialog.html
2017년 10월 12일 목요일
[Angular 2+] Form Submit 할 시 파일 포함하기 (multipart) - File Upload
Angular 로 파일 업로드 시 아래의 모듈을 많이 사용하는 것 같다.
1. ng2-file-upload
- https://github.com/valor-software/ng2-file-upload
2. ng2-fileupload
- https://github.com/thinkholic/ng2-fileupload
Angular 4
모듈이라는 개념에 맞게 순수하게 파일 업로드 기능만 들어있다.
저 모듈을 이용하게되면 우선 파일을 업로드 후 form submit 을 시켜야 할 것으로 보여진다.
서버 API 작업 시 multipart 로 text/file 파라메터를 동시에 받아 작업하는게 편한 경우가 있어 한번에 submit 시킬 수 있도록 작업을 했다.
작업환경: Angular 4
1004lucifer
multipart-form.service.ts
import {Injectable} from '@angular/core'; import {FormGroup} from '@angular/forms'; import {Headers, Http, Response} from '@angular/http'; import { Observable } from 'rxjs/Rx'; @Injectable() export class MultipartFormService { constructor( private http: Http ) { } /** * Form의 string / File 파라메터를 Multipart 로 묶어서 서버에 전송한다. * @param {string} url * @param {FormGroup} formGroup * @param {Array<{name: string; file: File}>} files - [{'name': 'fileKey1', 'file': this.file1}, ...] * @returns {Observable<Response>} */ sendMultipartForm(url: string, formGroup: FormGroup, files?: Array<{name: string, file: File}>): Observable<Response> { const formData = new FormData(); for (const key in formGroup.value) { if (formGroup.value.hasOwnProperty(key)) { formData.append(key, formGroup.value[key]); } } if (files) { files .filter((file) => file.name != null && file.file != null) // 정상적이지 않은 객체 Filter .forEach((file) => { formData.append(file.name, file.file); }); } const headers = new Headers({'enctype': 'multipart/form-data'}); return this.http.post(url, formData, { headers }); } }
사용 (실제 사용된 소스를 약간 수정했다.)
use.component.html
<div> <form [formGroup]="myForm" (ngSubmit)="onSubmit()"> <table class="tbl_w1 mrg_T20"> <colgroup> <col width="150"> <col width=""> </colgroup> <tr> <td>param1</td> <td><input formControlName="param1" type="text" class="white_grayline input_wmiddle back_gray"></td> </tr> <tr> <td>param2</td> <td><input formControlName="param2" type="text" class="white_grayline input_wmiddle back_gray"></td> </tr> <tr> <td>file1</td> <td><input #file1Name class="file_input_textbox2" readonly/> <div class="file_input_div"> <input type="button" value="찾아보기" class="file_input_button"/> <input (change)="file1 = extractFile($event); file1Name.value = extractFileName($event)" type="file" class="file_input_hidden"/> </div> </td> </tr> <tr> <td>file2</td> <td><input #file2Name class="file_input_textbox2" readonly/> <div class="file_input_div"> <input type="button" value="찾아보기" class="file_input_button"/> <input (change)="file2 = extractFile($event); file2Name.value = extractFileName($event)" type="file" class="file_input_hidden"/> </div> </td> </tr> </table> <p class="aln_c mrg_T20"> <button type="submit">확인</button> </p> </form> </div>
1004lucifer
use.component.ts
import {Component, Input, OnInit} from '@angular/core'; import {NgbActiveModal} from '@ng-bootstrap/ng-bootstrap'; import {FormControl, FormGroup} from '@angular/forms'; import {MultipartFormService} from './multipart-form.service'; @Component({ selector: 'use-selector', templateUrl: './use.component.html', styles: [] }) export class UseComponent implements OnInit { myForm: FormGroup; file1: File; file2: File; constructor( public activeModal: NgbActiveModal, private multipartFormService: MultipartFormService ) { this.myForm = new FormGroup({ 'param1': new FormControl(), 'param2': new FormControl() }); } ngOnInit() { } extractFile(event) { const files = event.target.files || event.srcElement.files; return files.length === 0 ? null : files[0]; } extractFileName(event) { const file = this.extractFile(event); return file ? file.name : ''; } onSubmit() { this.multipartFormService.sendMultipartForm( '/api/resourceName', this.myForm, // files 파라메터는 옵션으로 추가하지 않아도 된다. [{'name': 'fileKey1', 'file': this.file1}, {'name': 'fileKey2', 'file': this.file2}], ).subscribe( (response) => { console.log(response.json()); }, (response) => { console.log(response.json()); }); } /** onSubmit() { this.multipartFormService.sendMultipartForm( '/api/resourceName', this.myForm, ).subscribe( (response) => { console.log(response.json()); }, (response) => { console.log(response.json()); }); } */ }
use.module.ts
@NgModule({ imports: [ ReactiveFormsModule, ... ], declarations: [UseComponent], providers: [ MultipartFormService ], }) export class UseModule { }
참고
- http://nberserk.github.io/default/2017/02/12/angular-form-file.html
(사실상 위의 링크를 보고 만들었다.)
- https://www.angularjs4u.com/angularjs2/10-angular-2-file-upload-demos/
PS.
서버사이드를 Java Spring 을 사용하는데 위와같이 작업 시 이름이 같은 중복 파라메터는 보낼 수 없어 JSON 형식으로 객체를 보내는 방법으로 수정을 했는데 Content-Type 이슈로 인해 Spring 에서 JSON<=>객체 매핑이 제대로 되지 않았다.
아래와 같은 방법으로 Content-Type 헤더를 추가하여 이슈를 해결하였다.
링크: [Angular 2+] multipart 보낼 시 헤더에 Content-type 추가하기
라벨:
Angular
,
Content-Type
,
file
,
Upload
[Angular 2+] Button 태그 없이 Submit 수행하기
Angular 4 에서 <a> (Anchor Tag) 로 Submit 을 해야 하는 상황이 생겼다.
(퍼블리싱된 페이지를 보니 <button> 이 아니라 <a> 로 되어있었다.)
아래와 같이 작업을 했다. (O)
1004lucifer
<form [formGroup]="myForm" (ngSubmit)="onSubmit()"> <p class="aln_c mrg_T20"> <button type="submit" #submitBtn style="display:none;"></button> <a (click)="submitBtn.click()"><span class="btn_blue btn_popcon">확 인</span></a> <a (click)="activeModal.close()"><span class="btn_gray btn_popcon">취 소</span></a> </p> </form>
이것저것 해보며 아래와 같은 방법도 시도를 했는데,
아래와 같이 하게되면 페이지가 새로고침 되어버리므로 사용할 수가 없다. (X)
<form [formGroup]="myForm" (ngSubmit)="onSubmit()" #formElem> <p class="aln_c mrg_T20"> <a (click)="formElem.click()"><span class="btn_blue btn_popcon">확 인</span></a> <a (click)="activeModal.close()"><span class="btn_gray btn_popcon">취 소</span></a> </p> </form>
1004lucifer
PS.
(click) 속성으로 이렇게 저렇게 해보면서 한참을 시도 해봤는데 결국 button 태그가 꼭 있어야 ajax로 submit 이 가능했었다.ㅠ
다음엔 퍼블리싱 할 때 꼭 버튼은 button 태그를 이용해 달라고 이야기 해야 할듯..
submit without but
2017년 10월 8일 일요일
[Angular 2+] 브라우저 현재 URL 가져오기
Angular 4 사용하면서 상단의 네비게이션이 현재 주소에 맞게 보여지도록(선택된) 보여야 하는데 현재 보여지는 URL을 가지고 구성하면 되겠다고 생각해서 아래와 같이 URL을 가져와 네비게이션 작업을 했다.
1004lucifer
1. Router.url 사용
- https://angular.io/api/router/Router#url
2. Router Event를 Subscribe
- https://angular.io/api/router/Router#events
- https://angular.io/api/router/Event
menu.component.html
<div class="naviWrap"> <ul class="navi"> <li id="home" routerLink="/home/menu1" class="{{selectedMenu == 'home' ? 'on' : ''}}">홈</li> <li id="system" routerLink="/system/menu1" class="{{selectedMenu== 'system' ? 'on' : ''}}">시스템 설정</li> </ul> </div> <div id="homeSub" class="subnaviWrap" *ngIf="selectedMenu == 'home'"> <ul class="subnavi"> <li routerLink="/home/menu1" routerLinkActive="on">메뉴1</li> <li class="line">|</li> <li routerLink="/home/menu2" routerLinkActive="on">메뉴2</li> <li class="line">|</li> <li routerLink="/home/menu3" routerLinkActive="on">메뉴3</li> </ul> </div> <div id="homeSub" class="subnaviWrap" *ngIf="selectedMenu == 'system'"> <ul class="subnavi"> <li routerLink="/system/menu1" routerLinkActive="on">메뉴1</li> <li class="line">|</li> <li routerLink="/system/menu2" routerLinkActive="on">메뉴2</li> <li class="line">|</li> <li routerLink="/system/menu3" routerLinkActive="on">메뉴3</li> </ul> </div>
1004lucifer
MenuComponent.ts
export class MenuComponent implements OnInit { selectedMenu: string; constructor( private router: Router, ) { this.selectedMenu = 'home'; // /home/menu1 } ngOnInit() { // F5를 눌러 새로고침 시 MenuComponent가 초기화 되니 후 한번 실행 const currentUrl = this.router.url.split('/'); if (currentUrl[1]) { this.selectedMenu = currentUrl[1]; } // menu.component.html 에서 routerLink 선택하여 메뉴(URL)이동 할 때 마다 실행 this.router.events.subscribe((event) => { if (event instanceof NavigationEnd) { this.selectedMenu = event.url.split('/')[1]; } }); } }
PS.
- Router Event Subscribe 사용 시 상황에 맞게 사용해야 한다.
(main)AppModule 의 bootstrap에 등록된 Component 에서 Router Event Subscribe 사용할 시 모든 페이지(URL) 이동 시 이벤트가 발생을 하고,
MenuComponent 에서 등록한 Router Event Subscribe 는 해당 컴포넌트에서 발생한 이벤트만 수행이 된다.
2017년 10월 6일 금요일
[SSMS] '데이터베이스 복원' 작업 시 멈춤 현상
OS: Windows Server 2012 R2
DB: SQL Server 2016 Developer
Tool: SSMS(SQL Server Management Studio) 17
다른 PC(Server)의 MS SQL Server 백업한 파일을 복원하기 위해 아래와 같이 데이터베이스 복원 기능을 이요하여 복원하려했다.
1004lucifer
백업된 파일을 선택하니 아래와 같은 화면에서 멈추고 더 이상 진행이 되지 않았다.
인터넷으로 찾아봤는데 딱히 해결할 수 있는 명확한 방법이 나와있지 않고 SSMS를 repaire 하라는 이야기가 있었는데..
마침 사용하는 서버가 가상 서버이고 프로그램 설치 후 스냅샷을 생성한게 있어서 초기에 셋팅한 상태의 스냅샷 복구를 했다.
그동안 별다른 작업을 한것 같지는 않지만 별 문제 없이 다음으로 넘어가는 것을 확인 할 수 있었다.
추후 비슷한 문제 발생 시 SSMS 재설치를 한번 해봐야겠다.
PS.
아래의 로그가 추후 문제를 찾는데 도움이 될지는 모르겠지만 로그를 추가로 첨부를 한다.
Log Event ID 검색 시 해결방법에 대한 다른 글을 찾지 못했다.
로그 Windows NT (Application)
원본 Windows Error Reporting
범주 (0)
이벤트 1001
컴퓨터 WIN-AAAAA
메시지
오류 버킷 , 유형 0
이벤트 이름: AppHangB1
응답: 사용할 수 없음
Cab ID: 0
문제 서명:
P1: Ssms.exe
P2: 2017.140.17177.0
P3: 5982ac65
P4: 84f5
P5: 67246336
P6:
P7:
P8:
P9:
P10:
첨부 파일:
이 파일은 다음에서 사용할 수 있습니다.
C:\Users\Administrator\AppData\Local\Microsoft\Windows\WER\ReportQueue\Critical_Ssms.exe_5a36cc348872ae6636739daa81565639404590_d6281e50_13e4dda3
분석 기호:
해결 방법 재확인: 0
보고서 ID: 1eed0c54-a8a2-11e7-80c4-08002755ea12
보고서 상태: 4100
해시된 패킷:
로그 Windows NT (Application)
원본 Application Hang
범주 (101)
이벤트 1002
컴퓨터 WIN-AAAAAAA
메시지
프로그램 Ssms.exe 버전 2017.140.17177.0에서 Windows와의 상호 작용을 중지했으며 해당 프로그램이 종료되었습니다. 문제에 대한 자세한 정보가 있는지 알아보려면 관리 센터 제어판에서 문제 기록을 확인하십시오.
프로세스 ID: d10
시작 시간: 01d33cada1efdc61
종료 시간: 4294967295
응용 프로그램 경로: C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Ssms.exe
보고서 ID: 1eed0c54-a8a2-11e7-80c4-08002755ea12
오류 있는 패키지 전체 이름:
오류 있는 패키지에 상대적인 응용 프로그램 ID:
참고
- https://connect.microsoft.com/SQLServer/feedback/details/3103750/ssms-2016-hangs-frequently
- https://social.msdn.microsoft.com/Forums/sqlserver/en-US/520b5cfe-f746-4d62-954b-df195cca97e4/ssms-2012-locks-up-in-restore-database-dialog?forum=sqlkjmanageability
라벨:
멈춤
,
freezing
,
hang
,
SQL Server Management Studio
,
SSMS
피드 구독하기:
글
(
Atom
)