ASCII CODE
MIME TYPE (Multipurpose Internet Mail Extension)
Stream
Buffer
Blob (Binary Large Object)
배열을 넣어 Blob 객체를 생성함
const newBlob = new Blob(array, options);
new Blob([new ArrayBuffer(data)], { type: 'video/mp4' });
new Blob(new Uint8Array(data), { type: 'image/png' });
new Blob(['<div>Hello Blob!</div>'], {
type: 'text/html',
endings: 'native'
});
Blob 객체를 URL로 생성한다.
이 URL을 <a></a>(앵커) 태그에 연결 시키면 다운로드를 받을 수 있습니다. 서버에서 직접 다운로드를 받는 것이 아니라 브라우저 상에 저장되어 있는 blob파일을 다운로드 받게 됩니다. (아래 예제 코드)
Node.js
const stream = require('stream')
const fs = require('fs')
const spritesmith = require('spritesmith')
exports.downloadAllImages = async (req, res, next) => {
try {
logger.info('Download sprite sheet called')
const indexes = req.body.id
for (let i = 0; i < indexes.length; i++) {
const id = indexes[i]
if (!id || id < baseIndex || id > baseIndex + maxCount - 1) {
logger.error('Invalid parameter image id during download images')
next(ApiError.REQUEST_PARAMETER_NOT_VALIDATE)
}
}
const imageSrc = await getImagesByIndexes(indexes)
await spritesmith.run({ src: imageSrc }, (err, result) => {
if (err) {
throw err
} else {
const readStream = new stream.PassThrough()
readStream.end(result.image)
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-disposition': 'attachment;filename=sprite-sheet.png',
'Content-Length': result.image.length
})
readStream.pipe(res).on('close', function () {
logger.info('combine images to one sprite sheet and download file success')
})
}
})
} catch (e) {
logger.error(`Error occurred in unity module service during downloading all unity image:\\n${e.toString()}`)
next(ApiError.GENERAL_ERROR)
}
}
image file들을 불러와서 하나의 sprite sheet으로 변환하기 위해 sprite smith라는 module을 사용하였다.
sprite-sheet란 이름을 가진 png 파일로 변환 후 해당 Buffer를 Stream으로 client browser로 전송하였다.
Nuxt.js
async download () {
const response = await this.$axios.post('/unity/image/downloads', { id: [90000000, 90000001, 90000002] }, {
responseType: 'blob'
})
const url = window.URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', 'sprite-sheet' + '.png')
document.body.appendChild(link)
link.click()
link.remove()
}
Node.js
const stream = require('stream')
const fs = require('fs')
const AdmZip = require('adm-zip')
exports.downloadAllImages = async (req, res, next) => {
try {
logger.info('Download all images called')
const zip = new AdmZip()
const imageFilePaths = await getAllImages()
let missingFilePath = ''
let missingFileCount = 0
if (Array.isArray(imageFilePaths) && imageFilePaths.length > 0) {
imageFilePaths.forEach((v) => {
if (fs.existsSync(v)) {
zip.addLocalFile(v)
} else {
missingFilePath += `${v}\\n`
missingFileCount++
}
})
if (missingFileCount > 0) {
logger.error(`${missingFilePath} file is missing`)
zip.addFile('missing.txt', Buffer.from(missingFilePath, 'utf8'), '')
}
const zipFileName = getZipFileName(imageFilePaths.length, imageFilePaths.length - missingFileCount, missingFileCount)
const zipBuffer = zip.toBuffer()
const readStream = new stream.PassThrough()
readStream.end(zipBuffer)
res.writeHead(200, {
'Content-Type': 'application/zip',
'Content-disposition': `attachment;filename=${zipFileName}`,
'Content-Length': zipBuffer.length,
'File-Name': zipFileName
})
readStream.pipe(res).on('close', function () {
logger.info('Download zip file that compress all images success')
})
} else {
logger.error('There is no image file')
next(ApiError.GENERAL_ERROR)
}
} catch (e) {
logger.error(`Error occurred in unity module service during downloading all unity image:\\n${e.toString()}`)
next(ApiError.GENERAL_ERROR)
}
}
adm-zip 이란 module을 사용하였다.
Nuxt.js
async download () {
const res = await this.$axios.get('/unity/image/downloads', {
responseType: 'blob'
})
const url =window.URL.createObjectURL(newBlob([res.data]))
const link =document.createElement('a')
link.href = url
link.setAttribute('download', res.headers['file-name'])
document.body.appendChild(link)
link.click()
link.remove()
}