-
[API] MS API 이용하여 MS Office 파일 PDF로 변환하기 3 - 파일 업로드IT/API 2023. 5. 18. 21:38728x90반응형
이전 포스팅을 통해 MS Azure의 설정과 암호발급 까지 완료하였다면 이제 Azure의 API를 사용하여 MS cloud(OneDrive)에 파일을 업로드할 수 있다.
아래 포스팅에서 다룬 Node.js 에서 API 서버만들기를 통해 실제 API 서버를 구현해 볼 수 있다.
https://mongs-drawing.tistory.com/20
[Node.js] API 서버 만들기 2 - api 호출(get,post)
1. express 구조 파악 앞의 https://mongs-drawing.tistory.com/19 포스팅에서 설치한 express-generator를 이용하여 node.js 프레임워크를 만들었다면 아래와 같은 구조의 node.js 환경이 구축이 되어 있을 것이다. 상
mongs-drawing.tistory.com
1. 환경변수 설정
MS Azure에 접근하기 위해서 사용 하는 모든 API는 토큰 인증이 필수로 필요하다.
토큰을 발급받기 위해서는 tenant_id, client_id, client_secret 값이 필요한데 이는 이전 포스팅 https://mongs-drawing.tistory.com/21에서 발급받은 값을 토대로 입력할 수 있다.
tenant_id 와 client_id 는 MS Azure > AAD > 앱 등록 페이지에서 앱선택 시 바로 확인이 가능하고,
client_secret 는 인증서 및 암호 페이지에서 발급받은 암호의 값으로 확인이 가능하다.
express로 생성한 node.js 프로젝트 디렉터리에 환경변수를 담는 파일 .env를 생성하고 위의 값들을 저장시켜 놓는다.
OAUTH_CLIENT_ID='클라이언트 아이디' OAUTH_TENANT_ID='디렉터리 아이디' OAUTH_CLIENT_SECRET='암호 값'
2. Route 설정
express를 사용하여 정상적으로 프로젝트를 생성하였다면 root 경로에 app.js 파일이 있을 것이다. 이 app.js는 node module을 로딩하고 초기 initialize해야 하는 변수나 Object를 선언하고 Router에 유입이 이루어 지는 역할을 하는 JavaScript 파일이다.아래와 같이 수정을 진행하면 된다.
// express 모듈 var express = require('express'); // 파일 업로드를 위해 경로를 설정해주는 모듈 var path = require('path'); // Route 변수 설정 var uploadRouter = require('./routes/upload'); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(express.static(path.join(__dirname, 'public'))); // Route 설정 app.use('/upload', uploadRouter); module.exports = app;
3. 업로드 API 작성
app.js를 통해 클라이언트의 요청을 routes/upload.js 로 이동시키게 되고 upload.js 파일에서 업로드 API 요청을 처리한다.
우선 사용하는 모듈과 선언된 환경변수를 불러온다.
const path = require('path'); const multer = require('multer'); const fs = require('fs'); const request = require('request'); const jwt_decode = require('jwt-decode'); const axios = require('axios'); const url = require('url'); var express = require('express'); var router = express.Router(); require('dotenv').config(); const tenantId = process.env.OAUTH_TENANT_ID const clientId = process.env.OAUTH_CLIENT_ID const clientSecret = process.env.OAUTH_CLIENT_SECRET
이후 post 요청을 통해 클라이언트가 첨부한 파일을 받아오고, MS Azure에 업로드 하기위한 토큰이 서버에 존재하지 않다면 토큰 발급 API를 우선 호출한다.
// 클라이언트의 post 요청 처리 router.post('/', function(req, res, next) { const time_now = Math.floor(Date.now()/1000); const now = new Date(); // 토큰이 존재하지 않는다면 토큰 발급 API 호출 if(global.OAUTH_TOKEN == 'undefined' || global.OAUTH_TOKEN == null || global.OAUTH_EXPIRE == 'undefined' || global.OAUTH_EXPIRE < time_now + 60){ const params = new url.URLSearchParams({ grant_type: 'client_credentials', client_id: clientId, scope: 'https://graph.microsoft.com/.default', client_secret: clientSecret }) // MS Azure token을 발급하는 API로, 공식 홈페이지에 설명되어 있다. axios.post(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`, params.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded'}, method: 'post', }).then(function(response) { // axios 또한 ajax와 같은 비동기 처리기 때문에 토큰을 발급받기 이후 실행하기 위해 then 으로 처리한다. global.OAUTH_TOKEN = response.data.access_token global.OAUTH_EXPIRE = JSON.parse(JSON.stringify(jwt_decode(response.data.access_token).exp)) uploadToMS(); }) .catch(function(error) { console.log(error) }) } else { // 토큰이 이미 존재한다면 upload API 함수 호출 uploadToMS(); } } module.exports = router;
마지막으로 실질적으로 MS Azure로 업로드를 처리하는 API를 정의한 uploadToMS 함수를 호출하는 코드를 작성한다.
(위의 router.post 내부에 넣어야한다. 간단하게 마지막 중괄호 바로 위에 넣으면 제대로 동작한다.)
function uploadToMS(){ // 업로드 폴더 경로와 파일명을 변수로 설정한다. 프로젝트/publick/uploads 경로로 설정했다. const dir = path.resolve('','public','uploads') + '/' + time_now //__dirname + "/public/uploads/" + time_now; if(!fs.existsSync(dir)) fs.mkdirSync(dir); const storage = multer.diskStorage({ destination: function(req, file, cb) { cb(null, "public/uploads/" + time_now); }, filename: function (req, file, cb) { cb(null, time_now + path.extname(file.originalname)) } }); const upload = multer({storage:storage}).single('file') upload(req, res, (err) => { // MS Azure API에서 사용하면 에러가 발생하는 값은 제외시킨다. upload_filename = req.file.originalname.replace(/\#/g,'').replace(/\\/g,'').replace(/\\/g,'').replace(/\</g,'').replace(/\>/g,'') const filename = encodeURI(upload_filename); // 파일의 용량별로 사용되는 API가 다르다. // options 는 파일의 size가 4194300 보다 작을 때 사용할 수 있도록 정의한다. var options = { // 일반적으로 계정은 "유저아이디@xxx.onmicrosoft.com" 으로 되어있는데 이때 @을 url 인코딩 처리하여 %40으로 입력한다. url: `https://graph.microsoft.com/v1.0/users('계정')/drive/root:/${filename}:/content`, method: 'PUT', headers: { Authorization: `Bearer ${global.OAUTH_TOKEN}` } } // options_session 은 파일의 size가 4194300 보다 클 때 세션을 유지하며 업로드 하는 API를 사용하기 위해 정의한다. var options_session = { url: `https://graph.microsoft.com/v1.0/users('계정')/drive/root:/${filename}:/createUploadSession`, method: 'POST', headers: { Authorization: `Bearer ${global.OAUTH_TOKEN}` } } if(req.file.size < 4194300){ // 용량이 적을 때 fs.createReadStream(req.file.path) .pipe(request.put(options, (error, response, body) => { if (response.statusCode != 200 && response.statusCode != 201) { // 업로드가 실패했을 때 응답 코드이다. res.send({ status: response.statusCode, message : 'error', data: JSON.parse(response.body.toString()).error.message, dateTime: now }); } else { const file_id = JSON.parse(response.body.toString()).id; // 업로드가 성공하였을 때 응답 코드이다. res.json({ status: response.statusCode, message: 'success', data: { id: file_id, token: global.OAUTH_TOKEN }, dateTime: now }); } fs.unlinkSync(req.file.path) })) } else { // 용량이 클 때 request.put(options_session, (error, response, body) => { // 에러 발생 했을 때 응답 코드이다. if (error || (response.statusCode != 200 && response.statusCode != 201)) { res.send({ status: response.statusCode, message: 'error', data: JSON.parse(response.body.toString()).error.message, dateTime: now }); } else { // 업로드 세션이 성공적으로 연결되었을 때 호출 코드이다. const uploadUrl = JSON.parse(response.body.toString()).uploadUrl; const options_large = { url: uploadUrl, method: 'PUT', headers: { 'Content-Length': req.file.size, 'Content-Range': `bytes 0-${req.file.size-1}/${req.file.size}` } } fs.createReadStream(req.file.path) .pipe(request.put(options_large, (error_, response_, body) => { if (error_ || (response_.statusCode != 200 && response_.statusCode != 201)) { // 업로드가 실패하였을 때 응답 코드이다. res.send({ status: response_.statusCode, message : 'error', data: JSON.parse(response_.body.toString()).error.message, dateTime: now }); } else { // 업로드가 성공적으로 완료되었을 때 응답 코드이다. const file_id = JSON.parse(response_.body.toString()).id; res.json({ status: response_.statusCode, message: 'success', data: { id: file_id, token: global.OAUTH_TOKEN }, dateTime: now }); fs.unlinkSync(req.file.path) } })) } }) } }) }
여기까지 진행하였다면 MS Azure 클라우드에 파일이 업로드 되는 것을 콘솔에서 확인 할 수 있을 것이다.
* MS Azure API를 사용하여 MS Azure 클라우드에 업로드 하는 것이니 만큼 MS Office 파일 업로드만 지원된다.
업로드한 파일을 pdf로 변환하여 다운로드 하는 방법은 다음 포스팅에서 다루도록 하겠다.
728x90반응형'IT > API' 카테고리의 다른 글
[API] MS API 이용하여 MS Office 파일 PDF로 변환하기 4 - 파일 다운로드 (0) 2023.06.14 [API] MS API 이용하여 MS Office 파일 PDF로 변환하기 2 - MS Azure 클라이언트 암호 발급 (0) 2023.05.13 [API] MS API 이용하여 MS Office 파일 PDF로 변환하기 1 - MS Azure 설정 (0) 2023.05.08