前言
最近预研项目中需要实现图片上传存储,并且返回网络url进行回显,搜了几种方案,最终基于minio存储来实现,这里需要你的minio存储服务器已创建完成,创建服务器的过程可参考:blog.csdn.net/yhj_911/art…
然后我们基于已创建好的minio服务器,后端通过node.js来搭建接口,实现图片上传存储与回显。
基于node.js搭建后端服务接口
这里采用nestjs和eggjs两个框架搭建的后端服务分别来实现图片上传接口,前提是你已经基于这两个框架搭好了后端服务。 如何搭建后端服务参考:
基于nestjs环境下搭建图片上传存储接口
1、在src目录下创建minioSchema(名字自取)文件夹,然后分别创建
minioSchema.controller.ts;minioSchema.module.ts;minioSchema.service.ts 三个文件
2、在minioSchema.service.ts文件中,搭建服务函数
首先下载minio依赖
npm i minio
连接minio服务器
import Minio = require('minio');
const endPoint = '10.**.**.**' // 服务ip
const secretKey = '******' // 密码
console.log(process.env,"process.env")
const minioClient = new Minio.Client({
endPoint: endPoint,
port: 32666, // 服务端口
useSSL: false,
accessKey: '******', // 账号名
secretKey: secretKey,
});
编写服务函数
@Injectable()
export class MinioService {
async uploadImg(fileData,file: Buffer) {
const bucketName = 'img'
const fileName = `${new Date().getTime()}_${fileData.mimetype}`
await minioClient.putObject(bucketName, fileName, file,
{
'Content-Type': fileData.mimetype,
});
const url = `http://minio.***.net/${bucketName}/${fileName}`
// 返回可访问的图片url路径
return url
}
}
minioSchema.service.ts完整代码如下
import { Injectable } from '@nestjs/common';
import Minio = require('minio');
const endPoint = '10.**.**.**' // 服务ip
const secretKey = '******' // 密码
console.log(process.env,"process.env")
const minioClient = new Minio.Client({
endPoint: endPoint,
port: 32666, // 服务端口
useSSL: false,
accessKey: '******', // 账号名
secretKey: secretKey,
});
@Injectable()
export class MinioService {
async uploadImg(fileData,file: Buffer) {
const bucketName = 'img'
const fileName = `${new Date().getTime()}_${fileData.mimetype}`
await minioClient.putObject(bucketName, fileName, file,
{
'Content-Type': fileData.mimetype,
});
const url = `http://minio.***.net/${bucketName}/${fileName}`
// 返回可访问的图片url路径
return url
}
}
http://minio.***.net 为minio服务外部可访问的域名
2、在minioSchema.controller.ts文件中,搭建服务函数
import { Body, Request, Get, UseInterceptors, Post, Controller, UseGuards, Delete, UploadedFiles } from '@nestjs/common';
import { MinioService } from './minioSchema.service';
import { AnyFilesInterceptor } from '@nestjs/platform-express';
import { Request as Req } from 'express';
import { AuthGuard } from '@nestjs/passport';
import { ApiTags, ApiQuery, ApiOperation } from '@nestjs/swagger'
@Controller('api/minio')
@ApiTags('图片上传')
// @UseGuards(AuthGuard('jwt'))
export class MinioController {
constructor(
private readonly MinioService: MinioService,
) { }
@Post('upload')
@UseInterceptors(AnyFilesInterceptor())
@ApiOperation({ summary: '图片上传' })
async uploadImg(@UploadedFiles() files) {
const file = files[0];
try {
const url = await this.MinioService.uploadImg(file,file.buffer);
return {
code: 0,
data:url,
msg: "上传成功",
}
} catch (err) {
console.log(err,"err")
return{
code: 11,
data:null,
msg: "上传失败",
}
}
}
}
nestjs使用 UseInterceptors,AnyFilesInterceptor,UploadedFiles 来获取上传的文件files
3、在minioSchema.module.ts文件中引用搭建的服务
import { Module } from '@nestjs/common';
import { MinioController } from './minioSchema.controller';
import { MinioService } from './minioSchema.service';
@Module({
controllers: [MinioController],
providers: [MinioService]
})
export class MiniosModule {}
4、最后在app.module.ts引用搭建图片相关模块
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MiniosModule } from './minioSchema/minioSchema.module';
@Module({
imports: [
ConfigModule.forRoot(),
MongooseModule.forRoot(process.env.MONGODB_URL),
MiniosModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
到此,我们基于nestjs搭建的已有后端服务中,基于minio搭建的图片上传接口就可以了,如果上传成功,直接data中返回可访问的图片url,在前端界面进行回显
5、前端使用图片上传接口
这里直接使用element-plus框架的el-upload来实现
<script setup lang="ts">
import axios from 'axios'
const UploadImage = async (param) => {
let params = new FormData() //创建form对象
params.append('files', param.file) //通过append向form对象添加数据
const res = await axios.post('/api/minio/upload', params, {
headers: { 'Content-Type': 'multipart/form-data' },
})
}
</script>
<template>
<div >
<el-upload
class="upload-demo"
action="string"
:http-request="UploadImage"
>
<el-button type="default">点击上传</el-button>
</el-upload>
</div>
</template>
基于eggjs搭建环境实现图片上传存储接口
1、在controller问价夹下增加minio.ts文件
首先下载minio依赖和fs依赖
npm i minio
连接minio服务器
import Minio = require('minio');
import fs = require('fs');
const endPoint = '10.**.**.**' // 服务ip
const secretKey = '******' // 密码
const minioClient = new Minio.Client({
endPoint: endPoint,
port: 32666, // 服务端口
useSSL: false,
accessKey: '******', // 账号名
secretKey: secretKey,
});
创建接口服务函数
import BaseController from './base';
export default class MinioController extends BaseController {
// minioClient
public async uploadImg() {
const bucketName = this.ctx.request.body && this.ctx.request.body.bucketName || 'img';
const author = this.ctx.request.body && this.ctx.request.body.userName;//body中传的文件,看需求是否需要
const file = this.ctx.request.files[0];// 从request里面去files文件
const fileName = `${new Date().getTime()}_${file.filename}`;
await minioClient.putObject(bucketName, fileName, fs.createReadStream(file.filepath), {
'Content-Type': file.mime,
}); // fs.createReadStream(file.filepath),返回一个readStream(文件读取流,输入流)对象。(可读流)
const url = `http://minio.*****.net/${bucketName}/${fileName}`;
// 返回可访问的图片url路径 ,successRes base中封装的返回函数
this.successRes(url);
}
}
minio.ts完整代码如下
import BaseController from './base';
import Minio = require('minio');
import fs = require('fs');
const endPoint = '10.**.**.**' // 服务ip
const secretKey = '******' // 密码
const minioClient = new Minio.Client({
endPoint: endPoint,
port: 32666, // 服务端口
useSSL: false,
accessKey: '******', // 账号名
secretKey: secretKey,
});
export default class MinioController extends BaseController {
// minioClient
public async uploadImg() {
const bucketName = this.ctx.request.body && this.ctx.request.body.bucketName || 'img';
const author = this.ctx.request.body && this.ctx.request.body.userName;//body中传的文件,看需求是否需要
const file = this.ctx.request.files[0];// 从request里面去files文件
const fileName = `${new Date().getTime()}_${file.filename}`;
await minioClient.putObject(bucketName, fileName, fs.createReadStream(file.filepath), {
'Content-Type': file.mime,
}); // fs.createReadStream(file.filepath),返回一个readStream(文件读取流,输入流)对象。(可读流)
const url = `http://minio.*****.net/${bucketName}/${fileName}`;
// 返回可访问的图片url路径 ,successRes()为 base中封装的返回函数
this.successRes(url);
}
}
BaseController为公共返回函数,base.js文件如下
import { Controller } from 'egg';
export default class BaseController extends Controller {
errorRes(msg: string, code?: number, data?: any) {
this.ctx.body = {
code: code || -1,
msg,
data,
};
}
successRes(data?: any, msg?: string) {
this.ctx.body = {
code: 0,
msg: msg || '操作成功。',
data: data ?? null,
};
}
}
然后在router.ts中引用,抛出接口
import { Application } from 'egg';
export default (app: Application) => {
const {
controller,
router,
// io,
} = app;
router.post('/api/minio/uploadImg', controller.minio.uploadImg);
到此,我们基于eggjs的环境搭建的图片上传接口就可以使用了,前端使用接口方法和上述是一致的
前端代码:
<script setup lang="ts">
import axios from 'axios'
const UploadImage = async (param) => {
let params = new FormData() //创建form对象
params.append('files', param.file) //通过append向form对象添加数据
const res = await axios.post('/api/minio/upload', params, {
headers: { 'Content-Type': 'multipart/form-data' },
})
}
</script>
<template>
<div >
<el-upload
class="upload-demo"
action="string"
:http-request="UploadImage"
>
<el-button type="default">点击上传</el-button>
</el-upload>
</div>
</template>
备注:
我基于eggjs搭建的后端服务,获取的file文件中有 filepath,所有采用fs.createReadStream(file.filepath),返回一个readStream(文件读取流,输入流)对象来存储图片,在nestjs服务中,获得file文件中没有filepath,不过有二进制数据流对象buffer,所以可以通过直接传buffer存储图片
参考文档: