index.html 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Upload Test</title>
  6. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  7. <link rel="stylesheet" href="bootstrap.min.css"/>
  8. <style type="text/css">
  9. .drop_zone {
  10. background-color: #e0e0e0;
  11. border: #1b1e21 3px dot-dash;
  12. height: 100px;
  13. padding: 8px;
  14. font-size: 12px;
  15. }
  16. .inner_drop_zone {
  17. margin: 0 auto;
  18. padding: 0;
  19. text-align: center;
  20. }
  21. input[name="file"] {
  22. display: none;
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <div class="container-fluid">
  28. <nav class="navbar navbar-light bg-light">
  29. <h1 class="display-4">Kollus HTTP UPLOAD API SAMPLE</h1>
  30. <span class="navbar-text">HTTP API 를 이용한 컨텐츠 업로드 예제 샘플입니다.
  31. <p>자세한 사항은 아래의 링크를 이용하여 문서를 확인 바랍니다.</p>
  32. <a class="btn btn-primary" href="https://support.kollus.com" role="button">Learn more</a>
  33. </span>
  34. </nav>
  35. <div class="row">
  36. <div class="col-md-7 offset-1">
  37. <div class="input-group">
  38. <input type="text" class="form-control" name="access_token" placeholder="API Access Token"/>
  39. <div class="input-group-append">
  40. <button class="btn btn-outline-secondary" type="button" id="setAAT">시작</button>
  41. <button class="btn btn-outline-secondary" type="button" id="reset">취소</button>
  42. </div>
  43. </div>
  44. <div class="alert alert-warning alert-dismissible fade" role="alert">
  45. <strong>API 접근토큰</strong> 을 반드시 기입해주세요.
  46. <a href="http://kr.kollus.com/" class="alert-link">콜러스 콘솔</a>의 설정항목에서 확인해주세요
  47. <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  48. <span aria-hidden="true">&times;</span>
  49. </button>
  50. </div>
  51. <div class="drop_zone offset-3 col-md-6">
  52. <div class="inner_drop_zone" ondragover="return false;">
  53. <p>업로드할 파일을 여기에 올리거나 선택버튼을 눌러주세요</p>
  54. <button type="button" id="fileSelect">파일 선택</button>
  55. <input type="file" name="file"/>
  56. </div>
  57. <div class="file_info">
  58. </div>
  59. </div>
  60. <pre id="result"></pre>
  61. <div class="row">
  62. <div class="card col-md-6">
  63. <div class="card-header">
  64. Upload URL 획득
  65. </div>
  66. <ul class="list-group list-group-flush">
  67. <li class="list-group-item">
  68. <div class="input-group">
  69. <div class="input-group-prepend">
  70. <span class="input-group-text">카테고리키</span>
  71. </div>
  72. <select class="form-control" name="category_key">
  73. </select>
  74. </div>
  75. </li>
  76. <li class="list-group-item">
  77. <div class="input-group">
  78. <div class="input-group-prepend">
  79. <span class="input-group-text">만료시간</span>
  80. </div>
  81. <input type="number" class="form-control" name="expire_time" min="1" max="21600"
  82. value="600"/>
  83. </div>
  84. </li>
  85. <li class="list-group-item">
  86. <div class="row">
  87. <div class="btn-group-toggle" data-toggle="buttons">
  88. <label class="btn btn-outline-secondary" id="iau">
  89. <input type="checkbox" name="is_audio_upload"> 오디오 업로드
  90. </label>
  91. </div>
  92. <div class="btn-group-toggle" data-toggle="buttons">
  93. <label class="btn btn-outline-info">
  94. <input type="checkbox" name="is_encryption_upload"> 암호화 업로드
  95. </label>
  96. </div>
  97. <div class="btn-group-toggle" data-toggle="buttons">
  98. <label class="btn btn-outline-success">
  99. <input type="checkbox" name="is_passthrough"> 패스쓰루 업로드
  100. </label>
  101. </div>
  102. </div>
  103. </li>
  104. <li class="list-group-item">
  105. <div class="input-group">
  106. <div class="input-group-prepend">
  107. <span class="input-group-text">프로파일키</span>
  108. </div>
  109. <select class="form-control" name="profile_key">
  110. </select>
  111. </div>
  112. </li>
  113. <li class="list-group-item">
  114. <div class="input-group">
  115. <div class="input-group-prepend">
  116. <span class="input-group-text">컨텐츠타이틀</span>
  117. </div>
  118. <input type="text" class="form-control" name="title">
  119. </div>
  120. </li>
  121. <li class="list-group-item">
  122. <div class="input-group">
  123. <div class="input-group-prepend">
  124. <span class="input-group-text">업로드방식</span>
  125. </div>
  126. <select class="form-control" name="upload_type" disabled>
  127. <option value="n" selected>FormType</option>
  128. <option value="r">ResumeUpload(지원안함)</option>
  129. </select>
  130. </div>
  131. </li>
  132. </ul>
  133. </div>
  134. <div class="card col-md-6">
  135. <div class="card-header">
  136. <p>Upload 사용시 옵션</p>
  137. </div>
  138. <ul class="list-group list-group-flush">
  139. <li class="list-group-item">
  140. <div class="input-group">
  141. <div class="input-group-prepend">
  142. <span class="input-group-text">리다이렉트 URL</span>
  143. </div>
  144. <input type="text" class="form-control" name="return_url">
  145. </div>
  146. </li>
  147. <li class="list-group-item">
  148. <div class="btn-group-toggle" data-toggle="buttons">
  149. <label class="btn btn-outline-success">
  150. <input type="checkbox" name="disable_alert"> 업로드 완료후 알럿 띄우기
  151. </label>
  152. </div>
  153. </li>
  154. <li class="list-group-item">
  155. <div class="input-group">
  156. <div class="input-group-prepend">
  157. <span class="input-group-text">리다이렉트 스코프</span>
  158. </div>
  159. <select class="form-control" name="redirection_scope">
  160. <option value="outer" selected>Outer</option>
  161. <option value="inner">Inner</option>
  162. </select>
  163. </div>
  164. </li>
  165. <li class="list-group-item">
  166. <div class="input-group">
  167. <div class="input-group-prepend">
  168. <span class="input-group-text">Accept</span>
  169. </div>
  170. <input type="text" class="form-control" name="accept">
  171. </div>
  172. </li>
  173. </ul>
  174. </div>
  175. </div>
  176. </div>
  177. <div class="col-md-4">
  178. <div style="width:100%; height: 100%;">
  179. <div>
  180. <button type="button" class="btn btn-danger btn-lg" style="width:100%;" id="upload">UPLOAD</button>
  181. </div>
  182. <div class="progress" style="width: 100%;height: 30px;">
  183. <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
  184. style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">0%
  185. </div>
  186. </div>
  187. <pre style="width: 100%;" id="log"></pre>
  188. </div>
  189. </div>
  190. </div>
  191. </div>
  192. <script src="jquery-3.5.1.min.js"></script>
  193. <script src="bootstrap.bundle.min.js"></script>
  194. <script type="text/javascript">
  195. var MediaInfoJs = document.createElement('script');
  196. if ('WebAssembly' in window) {
  197. MediaInfoJs.src = "MediaInfoWasm.js";
  198. } else {
  199. MediaInfoJs.src = "MediaInfo.js";
  200. }
  201. document.body.appendChild(MediaInfoJs);
  202. var MediaInfoModule;
  203. var mediaInfoReady = false;
  204. var mediaInfo = undefined;
  205. var processing = false;
  206. var uploadFile = false;
  207. MediaInfoJs.onload = function () {
  208. MediaInfoModule = MediaInfoLib({
  209. 'postRun': function () {
  210. console.log('Load!!');
  211. mediaInfoReady = true;
  212. }
  213. });
  214. }
  215. window.onload = function () {
  216. var uploadFileList = false;
  217. var file = document.querySelector('input[name="file"]');
  218. $('.drop_zone').on('drag dragstart dragend dragover dragenter dragleave drop',
  219. function (e) {
  220. e.preventDefault();
  221. e.stopPropagation();
  222. })
  223. .on('drop', function (e) {
  224. parseFile(e.originalEvent.dataTransfer.files[0]);
  225. }
  226. );
  227. var fileSelect = document.getElementById('fileSelect');
  228. fileSelect.onclick = function () {
  229. file.click();
  230. }
  231. var file = document.querySelector('input[name="file"]');
  232. file.onchange = function () {
  233. parseFile(this.files[0]);
  234. }
  235. var parseFile = function (file) {
  236. if (processing) return;
  237. processing = true;
  238. mediaInfo = new MediaInfoModule.MediaInfo();
  239. mediaInfo.Open(file, function () {
  240. mediaInfo.Option('Inform')
  241. var fileName = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'FileName');
  242. var duration = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'Duration');
  243. var format = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'Format');
  244. var codec = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'CodecID');
  245. var filesize = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'FileSize');
  246. var bitrate = mediaInfo.Get(MediaInfoModule.Stream.General, 0, 'OverallBitRate');
  247. var file_info = $('<h6>' + fileName + '</h6>');
  248. if (duration == '' || format == '' || codec == '' || filesize == '' || bitrate == '') {
  249. file_info.append($('<span class="badge badge-danger">올바른 파일이 아닙니다.</span>'));
  250. } else {
  251. file_info.append($('<span class="badge badge-primary">' + format + '</span>'));
  252. file_info.append($('<span class="badge badge-secondary">' + codec + '</span>'));
  253. file_info.append($('<span class="badge badge-info">' + (filesize > (1024 * 1024) ? ((filesize / 1024 / 1024).toFixed(2) + 'MB') : ((filesize / 1024).toFixed(2) + 'KB')) + '</span>'));
  254. file_info.append($('<span class="badge badge-dark">' + new Date(parseInt(duration)).toISOString().slice(11, -1) + '</span>'));
  255. file_info.append($('<span class="badge badge-warning">' + (bitrate > (1024 * 1024) ? (bitrate / 1024 / 1024).toFixed(2) + 'mbps' : (bitrate / 1024).toFixed(2) + 'kbps') + '</span>'));
  256. }
  257. $('.file_info').append(file_info);
  258. mediaInfo.Close();
  259. mediaInfo.delete();
  260. processing = false;
  261. uploadFile = file;
  262. });
  263. }
  264. /*UI Control*/
  265. $('#setAAT').on('click', function () {
  266. var access_token = $('input[name="access_token"]').val();
  267. if (access_token === undefined || access_token.trim() === '') {
  268. $('.alert').addClass('show');
  269. }
  270. $.ajax(
  271. {
  272. url: 'https://api.kr.kollus.com/0/media/category/index?access_token=' + access_token,
  273. method: 'GET',
  274. success: function (res) {
  275. console.log(res);
  276. $.each(res.result.items.item, function (index, category) {
  277. $('select[name="category_key"]').append(
  278. $('<option value="' + category.key + '">' + category.name + '</option>')
  279. );
  280. });
  281. }
  282. });
  283. $.ajax(
  284. {
  285. url: 'https://api.kr.kollus.com/0/media/media_profile/index?access_token=' + access_token,
  286. method: 'GET',
  287. success: function (res) {
  288. console.log(res);
  289. $.each(res.result.items, function (index, profile) {
  290. $('select[name="profile_key"]').append(
  291. $('<option value="' + profile.key + '">' + profile.name + '</option>')
  292. );
  293. });
  294. }
  295. });
  296. });
  297. var is_passthrough = $('input[name="is_passthrough_upload"]').prop('checked')
  298. $('select[name="profile_key"]').attr('disabled', !is_passthrough);
  299. $('input[name="title"]').attr('disabled', is_passthrough);
  300. $('input[name="is_passthrough_upload"]').on('change', function (e) {
  301. $('select[name="profile_key"]').attr('disabled', !$(this).prop('checked'));
  302. $('input[name="title"]').attr('disabled', $(this).prop('checked'));
  303. });
  304. $('input[name="is_audio_upload"]').on('change', function (e) {
  305. var is_audio = $(this).prop('checked')
  306. if (is_audio) {
  307. $('input[name="is_passthrough_upload"]').prop('checked', false);
  308. }
  309. $('select[name="is_audio_upload"]').attr('disabled', !is_audio);
  310. });
  311. $('#upload').on('click', function () {
  312. if (!uploadFile) {
  313. alert('업로드할 파일을 선택해주세요.');
  314. return false;
  315. }
  316. var form = [];
  317. var category_key = $('select[name="category_key"] > option:selected').val();
  318. var expire_time = $('input[name="expire_time"]').val();
  319. if (expire_time > 0) {
  320. form.push(encodeURIComponent('expire_time') + '=' + encodeURIComponent(expire_time))
  321. }
  322. if (category_key !== undefined && category_key.trim() !== '') {
  323. form.push(encodeURIComponent('category_key') + '=' + encodeURIComponent(category_key))
  324. }
  325. if ($('input[name="is_audio_upload"]').prop('checked')) {
  326. form.push(encodeURIComponent('is_audio_upload') + '=' + encodeURIComponent(1))
  327. }
  328. if ($('input[name="is_encryption_upload"]').prop('checked')) {
  329. form.push(encodeURIComponent('is_encryption_upload') + '=' + encodeURIComponent(1))
  330. }
  331. if ($('input[name="is_passthrough"]').prop('checked')) {
  332. form.push(encodeURIComponent('is_passthrough') + '=' + encodeURIComponent(1))
  333. form.push(encodeURIComponent('profile_key') + '=' + encodeURIComponent($('select[name="profile_key"] > option:selected').val()))
  334. } else {
  335. var title = $('input[name="title"]').val();
  336. if (title !== undefined && title.trim() !== '') {
  337. form.push(encodeURIComponent('title') + '=' + encodeURIComponent(title))
  338. }
  339. }
  340. form.push(encodeURIComponent('upload_type') + '=' + encodeURIComponent($('select[name="upload_type"] > option:selected').val()))
  341. var access_token = $('input[name="access_token"]').val();
  342. var log = $('#log');
  343. $.ajax({
  344. url: 'http://upload.kr.kollus.com/api/v1/create_url?access_token=' + access_token,
  345. method: 'POST',
  346. ContentType: 'application/x-www-forurlencoded',
  347. data: form.join('&'),
  348. }).always(function (data, textStatus, xhr) {
  349. log.text(log.text() + '[CALL] http://upload.kr.kollus.com/api/v1/create_url?access_token=' + access_token + '\n');
  350. }).done(function (data) {
  351. log.text(log.text() + '====================== RESPONSE =======================\n');
  352. log.text(log.text() + JSON.stringify(data, null, 4) + '\n');
  353. upload(data);
  354. }).fail(function (xhr, textStatus, err) {
  355. console.log('fail: ', xhr + '\n');
  356. console.log('fail: ', textStatus);
  357. console.log('fail: ', err);
  358. });
  359. });
  360. var upload = function (data) {
  361. var log = $('#log');
  362. var purl = data.result['progress_url'];
  363. var uurl = data.result['upload_url'];
  364. var upload_data = new FormData();
  365. upload_data.append('upload-file', uploadFile);
  366. var redirection_url = $('input[name="return_url"]').val();
  367. if (redirection_url !== undefined && redirection_url.trim() !== '') {
  368. upload_data.append('return_url', return_url);
  369. }
  370. upload_data.append('disable_alert', $('input[name="disable_alert"]').prop('checked') ? 1 : 0);
  371. upload_data.append('redirection_scope', $('select[name="redirection_scope"] > option:selected').val());
  372. var accept = $('input[name="accept"]').val();
  373. if (accept !== undefined && accept.trim() !== '') {
  374. upload_data.append('accept', accept);
  375. }
  376. else {
  377. upload_data.append('accept', 'application/json');
  378. }
  379. $.ajax({
  380. url: uurl,
  381. method:'POST',
  382. mimeType: 'multipart/form-data',
  383. cache: false,
  384. contentType: false,
  385. processData: false,
  386. data: upload_data,
  387. timeout:0
  388. }).always(function (data, textStatus, xhr) {
  389. log.text(log.text() + '[CALL] ' + uurl + '\n');
  390. }).done(function (data) {
  391. log.text(log.text() + '====================== RESPONSE =======================\n');
  392. log.text(log.text() + JSON.stringify(data, null, 4) + '\n');
  393. }).fail(function (xhr, textStatus, err) {
  394. console.log('fail: ', xhr + '\n');
  395. console.log('fail: ', textStatus);
  396. console.log('fail: ', err);
  397. });
  398. var uploadInterval = setInterval(function () {
  399. $.get(purl, function (data) {
  400. $('.progress-bar').css('width', data.result.progress + '%');
  401. $('.progress-bar').html(data.result.progress + '%');
  402. log.text(log.text() + '[progress] ' + data.result.progress + '%\n');
  403. if (data.result.progress >= 100) {
  404. clearInterval(uploadInterval);
  405. }
  406. });
  407. }, 1000);
  408. }
  409. }
  410. </script>
  411. </body>
  412. </html>