本文说明 node中两大框架:nest.js 和 egg.js
需要依赖 ali-oss 这个阿里云提供的库
环境1:Nest.js
方法一:
先上传到服务器,再从服务器中转到 阿里云
// controller.ts
@Post('oss')
@UseInterceptors(
FileInterceptor('file', {
storage: multer.diskStorage({
destination: (req, file, cb) => {
// 开启服务器本地存储路径
cb(null, 'D:/barry/temp');
},
filename: (req, file, cb) => {
cb(null, file.originalname);
},
}),
}),
)
// 接着上传到oss
async uploadImage(@UploadedFile() file: any): Promise<any> {
return await this.uploadService.uploadImage(file);
}
// upload.service.ts
async uploadImage(file: any): Promise<any> {
try {
const ossService = new OssService();
const ossUrl = await ossService.putOssFile(
`/slideShow/${file.originalname}`, // 存放的 ali-oss 位置
`D:/barry/temp/${file.originalname}`, // 存放的本地(服务器的位置)
);
return {
code: 200,
data: ossUrl,
message: '上传成功',
};
} catch (error) {
return {
code: 503,
msg: `Service error: ${error}`,
};
}
}
利用 ali-oss 提供的 put 方法
// oss.service.ts
public constructor() {
this.client = new OSS({
accessKeyId: ossConfig.accessKeyId,
accessKeySecret: ossConfig.accessKeySecret,
region: ossConfig.region,
bucket: ossConfig.bucket,
});
}
// 上传文件到oss 并返回 图片oss 地址
public async putOssFile(ossPath: string, localPath: string): Promise<string> {
let res: any;
try {
res = await this.client.put(ossPath, localPath);
// 将文件设置为公共可读
await this.client.putACL(ossPath, 'public-read');
} catch (error) {
console.log(error);
}
return res.url;
}
这个方法有个问题就是:必须要依赖服务器做中转,也就是服务器存一份,阿里云存一份。
方法二:
直接上传到阿里云
// upload.controller.ts
@Post('oss')
@UseInterceptors(FileInterceptor('file', {}))
async uploadImage(@UploadedFile() file: any): Promise<any> {
await this.uploadService.uploadImage(file);
}
}
// upload.service.ts
async uploadImage(file: any): Promise<any> {
try {
const ossService = new OssService();
const ossUrl = await ossService.putOssFile(file);
return {
code: 200,
data: ossUrl,
message: '上传成功',
};
} catch (error) {
return {
code: 503,
msg: `Service error: ${error}`,
};
}
}
利用 ali-oss 的 putStream 方法
import { Readable } from 'stream';
public async putOssFile(file): Promise<string> {
/**
* 将buffer转为Stream流
* @param binary file.buffer
* @returns
*/
function bufferToStream(binary) {
const readableInstanceStream = new Readable({
read() {
this.push(binary);
this.push(null);
},
});
return readableInstanceStream;
}
const res = await this.client.putStream('others/b.png', bufferToStream(file.buffer), {
contentLength: file.size,
});
return res.url;
}
环境2:Egg.js
直接上传到阿里云
egg自带有multipart,不再需要额外转换Stream流,听说是封装的co-busboy
// upload.js
// 阿里云oss
const client = new oss({
accessKeyId: ossConfig.accessKeyId,
accessKeySecret: ossConfig.accessKeySecret,
region: ossConfig.region,
bucket: ossConfig.bucket,
});
/**
* 上传处理
*/
async doAdd() {
const { ctx, service, app } = this;
// 利用 egg 提供的 multipart 将文件转为流式Stream类型
let parts = ctx.multipart({ autoFields: true });
let stream;
client
.listBuckets({
'max-keys': 10,
})
.then((result) => {
console.log(result);
});
while ((stream = await parts()) != null) {
if (!stream.filename) {
break;
}
// 修改名字 以及对应的阿里云路径
let name = `test${path.extname(stream.filename)}`;
client
.putStream(name, stream)
.then(function (r1) {
console.log('put success: %j', r1);
return client.get('object');
})
.then(function (r2) {
console.log('get success: %j');
})
.catch(function (err) {
console.error('error: %j');
});
}
ctx.body = 'ok';
}
删除阿里云的文件
只需要调用 ali-oss 提供的 delete 方法即可
/**
* 删除oss文件
*/
public async deleteOssFile() {
const resp = await this.client.delete('slideShow/b.png'); // 阿里云文件路径
console.log('删除成功??', resp);
}