본문 바로가기

잡단한것들/코딩연습장

Tus프로토콜을 사용한 업로드

const input = document.getElementById('input');
input.addEventListener("change"function (e) {
    const files = e.target.files;
    function tusUpload(files) {
        [].map.call(files, (file, index) => {
            var upload = new tus.Upload(file, {
                endpoint: 'http://localhost:5000/uploads',
                retryDelays: [0300050001000020000],
                metadata: {
                    filename: file.name,
                    filetype: file.type
                },
                chunkSize: 8 * 1024 * 1024// 8MB
                onError: function (error) {
                    console.log("Failed because: " + error)
                },
                onProgress: function (bytesUploaded, bytesTotal) {
                    var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2)
                    console.log(bytesUploaded, bytesTotal, percentage + "%")
                },
                onSuccess: function () {
                    console.log("Download %s from %s", upload.file.name, upload.url)
                }
            })
            console.log(file.name)
            upload.findPreviousUploads().then(function (previousUploads) {
                if (previousUploads.length) {
                    upload.resumeFromPreviousUpload(previousUploads[0])
                }
                // Start the upload
                upload.start();
                return console.log('start');
            })
        })
    }
    tusUpload(files);
})

map함수를 통하여 파일리스트의 길이 만큼 다중파일 업로드를 구현했다.

Tus에서는 싱글파일업로드만 지원해서 다중파일을 업로드해야된다면 이렇게 Tus인스턴스를 계속 생성하는 방법 밖에는 없는것 같다.

//REQUIRE MODULES
const express = require('express');
const tus = require('tus-node-server');
const cors = require('cors');
const { Base64 } = require('js-base64');
const EVENTS = require('tus-node-server').EVENTS;
//CREATE SERVER
const tusServer = new tus.Server();
const fileNameFromUrl = (req) => {
    const value = req.get('upload-metadata');
    // console.log(value);
    const keyPairs = value.split(',')
        .map((F) => F.trim().split(' '));
    // console.log(keyPairs);
    const originFileName = keyPairs.find(T => T[0=== 'filename')[1];
    return Base64.decode(originFileName);
}
tusServer.datastore = new tus.FileStore({
    path: '/uploads',
    namingFunction: fileNameFromUrl
});
tusServer.on(EVENTS.EVENT_UPLOAD_COMPLETE, (event) => {
    console.log(`Upload complete for file ${event.file.id}`);
});
const app = express();
const uploadApp = express();
//MIDDLEWARE
uploadApp.all('*', tusServer.handle.bind(tusServer));
app.use('/uploads', uploadApp);
app.use(cors());
app.timeout = 1000 * 60 * 10// 10 mins
//CONNECT PORT
const port = process.env.PORT || 5000;
const host = '127.0.0.1';
app.listen(port, host, () => {
    console.log(`[${new Date().toLocaleTimeString()}] tus server listening at http://${host}:${port}`);
});

Tus는 기본적으로 파일의 이름과 확장자 명에 대한 정보가 담겨 있지 않다.

따라서 메타데이터 객체에 filename과 filetype이라는 키로 담아서 가져온뒤 문자열을 분리하여 필요한 값만 추출하면 된다. 참고로 담겨져 온 값들은 암호화 되있어서 디코드 해줘야한다. 디코드는 js-base64라는 모듈을 사용하였다.