Node.js 操作百度网盘实现文件上传(小文件上传,大文件分片上传)
前提准备:获取百度网盘的授权码
https://pan.baidu.com/union/doc/al0rwqzzl
const fs = require('fs');
const crypto = require('crypto');
const path = require('path');
const FormData = require('form-data');
const axios = require('axios');
const access_token = '需要自己创建应用获取授权码'
async function readFile(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
function getFileInfo(filePath) {
return new Promise((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (err) {
reject(err);
} else {
resolve({
size: stats.size,
isFile: stats.isFile(),
name: path.basename(filePath)
});
}
});
});
}
function getSlice(filePath, start, end) {
return new Promise((resolve, reject) => {
const sliceStream = fs.createReadStream(filePath, {
start,
end
});
let chunk = '';
sliceStream.on('data', (data) => {
chunk += data;
});
sliceStream.on('end', () => {
resolve(chunk);
});
sliceStream.on('error', (err) => {
reject(err);
});
});
}
async function getFileMd5List(filePath) {
try {
const fileInfo = await getFileInfo(filePath);
const sliceSize = 4 * 1024 * 1024; // 4MB
if (fileInfo.size <= sliceSize) {
// 如果文件小于等于4MB,直接计算整个文件的MD5并返回
const fileData = await readFile(filePath);
const fileMd5 = crypto.createHash('md5').update(fileData).digest('hex');
return JSON.stringify([fileMd5]);
} else {
// 如果文件大于4MB,分片计算MD5
const sectionCount = Math.ceil(fileInfo.size / sliceSize);
const md5List = [];
for (let i = 0; i < sectionCount; i++) {
const sliceData = await getSlice(filePath, i * sliceSize, (i + 1) * sliceSize - 1);
const sliceMd5 = crypto.createHash('md5').update(sliceData).digest('hex');
md5List.push(sliceMd5);
}
return JSON.stringify(md5List);
}
} catch (error) {
console.error('Error in getFileMd5List:', error);
return null;
}
}
async function uploadFileToBaidu(filePath, accessToken) {
try {
const fileInfo = await getFileInfo(filePath);
let md5List = await getFileMd5List(filePath);
console.log(md5List)
const precreateRes = await axios.post('https://pan.baidu.com/rest/2.0/xpan/file', {
path: '/apps/后台管理系统/' + fileInfo.name,
size: fileInfo.size,
isdir: fileInfo.isFile ? 0 : 1,
rtype: 1,
autoinit: 1,
block_list: md5List
}, {
params: {
method: 'precreate',
access_token: accessToken
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const uploadId = precreateRes.data.uploadid;
if (fileInfo.isFile && fileInfo.size <= 4 * 1024 * 1024) {
// 小文件上传
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
const uploadSingle = await axios.post('https://d.pcs.baidu.com/rest/2.0/pcs/file', form, {
params: {
method: 'upload',
access_token: accessToken,
path: '/apps/后台管理系统/' + fileInfo.name,
ondup: 'overwrite'
},
headers: {
...form.getHeaders(),
}
})
;
return;
} else {
const sliceSize = 4 * 1024 * 1024;
const sectionCount = Math.ceil(fileInfo.size / sliceSize);
md5List = []
for (let i = 0; i < sectionCount; i++) {
const form = new FormData();
form.append('file', await getSlice(filePath, i * sliceSize, (i + 1) * sliceSize - 1));
if (i === sectionCount - 1) {
form.append('file', await getSlice(filePath, i * sliceSize, fileInfo.size - 1));
}
const sectionItem = await axios.put('https://d.pcs.baidu.com/rest/2.0/pcs/superfile2', form, {
params: {
method: 'upload',
access_token: accessToken,
type: 'tmpfile',
path: '/apps/后台管理系统/' + fileInfo.name,
uploadid: uploadId,
partseq: i
},
headers: {
...form.getHeaders(),
}
});
md5List.push(sectionItem.data.md5)
}
console.log(md5List)
const uploadArray = await axios.post('https://pan.baidu.com/rest/2.0/xpan/file', {
path: '/apps/后台管理系统/' + fileInfo.name,
size: fileInfo.size,
isdir: fileInfo.isFile ? 0 : 1,
uploadid: uploadId,
block_list: JSON.stringify(md5List)
}, {
params: {
method: 'create',
access_token: accessToken
},
headers: {
'User-Agent': 'pan.baidu.com',
'Content-Type': 'application/x-www-form-urlencoded',
},
});
console.log(uploadArray.data)
}
} catch (e) {
console.log('error', e)
}
}
// uploadFileToBaidu(path.resolve(__dirname, './WeChatProjects.zip'), access_token)
// uploadFileToBaidu(path.resolve(__dirname, './auth.js'), access_token)