mirror of
https://github.com/NeteaseCloudMusicApiEnhanced/api-enhanced.git
synced 2026-03-21 19:13:10 +00:00
feat(cloud): 支持临时文件上传功能
- 使用 crypto 模块替换 md5 模块进行文件哈希计算 - 添加对临时文件上传的支持,当存在 tempFilePath 时使用文件流处理 - 实现临时文件的 MD5 计算和元数据解析功能 - 在上传完成后自动清理临时文件 - 配置服务器端文件上传中间件启用临时文件支持 - 修改上传插件以支持临时文件读取流上传方式 - 增加文件大小获取和验证的兼容性处理
This commit is contained in:
parent
26d55255e0
commit
ba7d1a8574
@ -1,5 +1,6 @@
|
|||||||
const uploadPlugin = require('../plugins/songUpload')
|
const uploadPlugin = require('../plugins/songUpload')
|
||||||
const md5 = require('md5')
|
const crypto = require('crypto')
|
||||||
|
const fs = require('fs')
|
||||||
const createOption = require('../util/option.js')
|
const createOption = require('../util/option.js')
|
||||||
const logger = require('../util/logger.js')
|
const logger = require('../util/logger.js')
|
||||||
let mm
|
let mm
|
||||||
@ -26,17 +27,40 @@ module.exports = async (query, request) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (!query.songFile.md5) {
|
|
||||||
query.songFile.md5 = md5(query.songFile.data)
|
const useTempFile = !!query.songFile.tempFilePath
|
||||||
query.songFile.size = query.songFile.data.byteLength
|
let fileSize = query.songFile.size
|
||||||
|
let fileMd5 = query.songFile.md5
|
||||||
|
|
||||||
|
if (useTempFile) {
|
||||||
|
const stats = fs.statSync(query.songFile.tempFilePath)
|
||||||
|
fileSize = stats.size
|
||||||
|
if (!fileMd5) {
|
||||||
|
fileMd5 = await new Promise((resolve, reject) => {
|
||||||
|
const hash = crypto.createHash('md5')
|
||||||
|
const stream = fs.createReadStream(query.songFile.tempFilePath)
|
||||||
|
stream.on('data', (chunk) => hash.update(chunk))
|
||||||
|
stream.on('end', () => resolve(hash.digest('hex')))
|
||||||
|
stream.on('error', reject)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!fileMd5) {
|
||||||
|
fileMd5 = crypto.createHash('md5').update(query.songFile.data).digest('hex')
|
||||||
|
}
|
||||||
|
fileSize = query.songFile.data.byteLength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query.songFile.md5 = fileMd5
|
||||||
|
query.songFile.size = fileSize
|
||||||
|
|
||||||
const res = await request(
|
const res = await request(
|
||||||
`/api/cloud/upload/check`,
|
`/api/cloud/upload/check`,
|
||||||
{
|
{
|
||||||
bitrate: String(bitrate),
|
bitrate: String(bitrate),
|
||||||
ext: '',
|
ext: '',
|
||||||
length: query.songFile.size,
|
length: fileSize,
|
||||||
md5: query.songFile.md5,
|
md5: fileMd5,
|
||||||
songId: '0',
|
songId: '0',
|
||||||
version: 1,
|
version: 1,
|
||||||
},
|
},
|
||||||
@ -46,10 +70,15 @@ module.exports = async (query, request) => {
|
|||||||
let album = ''
|
let album = ''
|
||||||
let songName = ''
|
let songName = ''
|
||||||
try {
|
try {
|
||||||
const metadata = await mm.parseBuffer(
|
let metadata
|
||||||
query.songFile.data,
|
if (useTempFile) {
|
||||||
query.songFile.mimetype,
|
metadata = await mm.parseFile(query.songFile.tempFilePath)
|
||||||
)
|
} else {
|
||||||
|
metadata = await mm.parseBuffer(
|
||||||
|
query.songFile.data,
|
||||||
|
query.songFile.mimetype,
|
||||||
|
)
|
||||||
|
}
|
||||||
const info = metadata.common
|
const info = metadata.common
|
||||||
|
|
||||||
if (info.title) {
|
if (info.title) {
|
||||||
@ -73,7 +102,7 @@ module.exports = async (query, request) => {
|
|||||||
local: false,
|
local: false,
|
||||||
nos_product: 3,
|
nos_product: 3,
|
||||||
type: 'audio',
|
type: 'audio',
|
||||||
md5: query.songFile.md5,
|
md5: fileMd5,
|
||||||
},
|
},
|
||||||
createOption(query),
|
createOption(query),
|
||||||
)
|
)
|
||||||
@ -98,15 +127,22 @@ module.exports = async (query, request) => {
|
|||||||
} catch (uploadError) {
|
} catch (uploadError) {
|
||||||
logger.error('Upload failed:', uploadError)
|
logger.error('Upload failed:', uploadError)
|
||||||
return Promise.reject(uploadError)
|
return Promise.reject(uploadError)
|
||||||
|
} finally {
|
||||||
|
if (useTempFile && fs.existsSync(query.songFile.tempFilePath)) {
|
||||||
|
fs.unlinkSync(query.songFile.tempFilePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info('File already exists, skip upload')
|
logger.info('File already exists, skip upload')
|
||||||
|
if (useTempFile && fs.existsSync(query.songFile.tempFilePath)) {
|
||||||
|
fs.unlinkSync(query.songFile.tempFilePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res2 = await request(
|
const res2 = await request(
|
||||||
`/api/upload/cloud/info/v2`,
|
`/api/upload/cloud/info/v2`,
|
||||||
{
|
{
|
||||||
md5: query.songFile.md5,
|
md5: fileMd5,
|
||||||
songid: res.body.songId,
|
songid: res.body.songId,
|
||||||
filename: query.songFile.name,
|
filename: query.songFile.name,
|
||||||
song: songName || filename,
|
song: songName || filename,
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const { default: axios } = require('axios')
|
const { default: axios } = require('axios')
|
||||||
|
const fs = require('fs')
|
||||||
const createOption = require('../util/option.js')
|
const createOption = require('../util/option.js')
|
||||||
const logger = require('../util/logger.js')
|
const logger = require('../util/logger.js')
|
||||||
module.exports = async (query, request) => {
|
module.exports = async (query, request) => {
|
||||||
@ -71,6 +72,14 @@ module.exports = async (query, request) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useTempFile = !!query.songFile.tempFilePath
|
||||||
|
let uploadData
|
||||||
|
if (useTempFile) {
|
||||||
|
uploadData = fs.createReadStream(query.songFile.tempFilePath)
|
||||||
|
} else {
|
||||||
|
uploadData = query.songFile.data
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios({
|
await axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -81,7 +90,7 @@ module.exports = async (query, request) => {
|
|||||||
'Content-Type': 'audio/mpeg',
|
'Content-Type': 'audio/mpeg',
|
||||||
'Content-Length': String(query.songFile.size),
|
'Content-Length': String(query.songFile.size),
|
||||||
},
|
},
|
||||||
data: query.songFile.data,
|
data: uploadData,
|
||||||
maxContentLength: Infinity,
|
maxContentLength: Infinity,
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
timeout: 300000,
|
timeout: 300000,
|
||||||
|
|||||||
@ -183,11 +183,12 @@ async function consturctServer(moduleDefs) {
|
|||||||
|
|
||||||
app.use(fileUpload({
|
app.use(fileUpload({
|
||||||
limits: {
|
limits: {
|
||||||
fileSize: 500 * 1024 * 1024 // 500MB
|
fileSize: 500 * 1024 * 1024
|
||||||
},
|
},
|
||||||
useTempFiles: false,
|
useTempFiles: true,
|
||||||
tempFileDir: '/tmp/',
|
tempFileDir: require('os').tmpdir(),
|
||||||
abortOnLimit: true
|
abortOnLimit: true,
|
||||||
|
parseNested: true
|
||||||
}))
|
}))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user