[a tag]
<a href={questionModalSrc} download="88a2f203a144c233726b8ffcdccc9ed8.png">
- download='img.png'에서 img.png는 변경가능
- 확장자 안쓰면 알아서 다운로드시 Type에 해당하는 확장자 붙여줌,
- img.htm이런식으로 확장자 잘못 붙여도 다운로드 가능
[모든 element에 적용가능한 방법] 클릭시 임시로 a tag생성하고 클릭되도록
onClick={() => { const link = document.createElement('a');
link.href = \`/common/files/01. CDP Admin Operation Policy.docx\`;
link.target = '\_blank';//링크클릭시 새창에서 열도록, 링크여는목적 아니므로 없어도 될듯
link.download = '다운로드될 파일명'; 이 부분이 없으면 자동다운로드 안됨
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}}
외부에 있는 자원을 다운로드
API 구현부분
- 테스트해보니 요청하는 헤더내의 content_type: application/json이지만 응답헤더의 Content-Type: application/octet-stream
Content-Disposition: attachement; filename="RBSPOT.json"로 응답함 - 참고로 다른 요청->응답은 아래와 같았음
- 일반적인 json Fetch/XHR request -> response
- content-type: application/json -> Content-Type: application/json;charset=UTF-8
- 파일을 자동으로 다운로드되도록 하는 request -> response
- content-type: application/json -> Content-Type: application/octet-stream
Content-Disposition: attachement; filename="RBSPOT.json"
- content-type: application/json -> Content-Type: application/octet-stream
- 파일을 서버로 업로드하는 request -> response
- Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCr6S7zpBWkWbkGAB ->
- 일반적인 json Fetch/XHR request -> response
@Description("MetaDataFile Download from Admin.")
@GetMapping
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping("/api/admin/apiCallLog/{apiCallLogId}/file")
public ResponseEntity<?> getMetaDataFile(@CurrentUser UserPrincipal currentUser,
@PathVariable Long apiCallLogId) {
Map<String, Object> resultMap = new HashMap<String, Object>();
URL url = new URL(...어찌어찌해서 얻어옴);
InputStreamResource resource = new InputStreamResource(url.openStream());
resultMap.put("fileName", apiCallInfo.getFileName());
resultMap.put("resource", resource);
return ResponseEntity.ok().contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachement; filename=\"" + resultMap.get("fileName") + "\"")
.body(resultMap.get("resource"));
}
구현된 API call하는 부분
export async function getFileDownload(requestPath, requestMethod, rowData) {
await fetch(API_BASE_URL + requestPath, {
method: 'GET',
headers: getHeaders(),
})
.then(response => {
return response.blob();
})
.then(blob => {
const url = window.URL.createObjectURL(
new Blob([blob]),
);
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
rowData.fileName,
);//filename to be downloaded, it can be used as link.download=fileName
//link.style='display:none'; //OK it is not given
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
})
.catch(err => {
alert('error')
});
}
서버 내부 자원(public공간내 file) 다운로드
<button
type="button"
className="quick_link link1"
onClick={() => {
const link = document.createElement('a');
link.href = `/common/files/01. CDP Admin Operation Policy_(ENG)20210428.docx`;
link.target = '_blank';
link.download = '01. CDP Admin Operation Policy_(ENG)20210428.docx';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}}>
서버응답을 받아 파일을 내려주거나 내부소스 파일을 내려주거나 다운로드 하는 부분의 공통점
const link = document.createElement('a');
link.href = `/common/files/01. CDP Admin Operation Policy_(ENG)20210428.docx`;//여기에서 차이남
//link.target = '_blank'; //없어도됨
link.download = '01. CDP Admin Operation Policy_(ENG)20210428.docx'; //link.setAttribute('download', 파일명)과 동일
document.body.appendChild(link);
link.click();
document.body.removeChild(link);//link.remove(); link.parentNode.removeChild(link);와 동일
서버응답을 받아 파일생성하는 부분
new Blob([arrayContetns], options) options는 생략가능
new Blob([response], {type" res.headers[content-type]})
Blob을 URL로 변환
window.URL.createObjectURL(blob)
URL.revokeObjectURL( window.URL.createObjectURL(blob) ) 여기서 window.URL=URL인듯