在前端页面中,采用了uview的上传组件u-upload。详情参数请参考uview官网:https://www.uviewui.com/components/upload.html
template中的主要页面代码
<!--图片上传-->
<u-upload
:capture="['camera']"
@afterRead="afterRead"
:maxCount="1"
:previewFullImage="true"
></u-upload>
<image v-show="entity.zpurl!=null" style="width: 100%;height: 300px;" :src="entity.zpurl"></image>
<!-- 画布 -->
<view style='width:0px;height:0px;overflow:hidden;'>
<canvas canvas-id="cid" :style="{height:`${cvHeight}px`,width:`${cvWidth}px`}"></canvas>
</view>
data中定义的属性
data() {
return {
entity:{
zpurl:null,
},
cvHeight:'',
cvWidth:'',
}
},
methods中的方法
// 保存上传图片
async afterRead(event) {
const _this = this;
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
for (let i = 0; i < lists.length; i++) {
// 不加水印打开下面两行代码,注释下面代码
//const tpurl = await this.uploadFilePromise(lists[i].url);
//this.entity.zpurl = tpurl;
// 加水印使用下面代码
const tpurl = lists[i].url;
const sytext = '拍摄时间 : ' + _this.getNowFormatTime(); // 水印内容
uni.getImageInfo({
src: tpurl,
complete: function (image) {
// 动态设置canvas宽高
_this.cvHeight = image.height;
_this.cvWidth = image.width;
setTimeout(()=>{
_this.imgToCanvas(tpurl, image.width, image.height,sytext);
},200)
}
});
}
},
// 给图片添加水印
// url:图片url;width:图片宽度;height:图片高度,text:水印文字
imgToCanvas(url, width, height, text) {
const ctx = uni.createCanvasContext('cid');
ctx.drawImage(url, 0, 0,width,height);
// 设置水印的位置
ctx.font="24px Georgia";
ctx.fillStyle = "red";
ctx.fillText(text, 50, 30);
//绘制到canvas上
ctx.draw()
const timer = setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: 'cid',
fileType: 'jpg',
success: (res) => {
this.setFilePath(res.tempFilePath); // 将添加的水印保存minio
}
}, this)
clearTimeout(timer)
}, 500)
},
async setFilePath(path){
const tpurl = await this.uploadFilePromise(path); // 上传方法
this.entity.zpurl = tpurl; // 将上传成功的图片地址返回
},
// 上传图片
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
uni.showLoading({
title: '正在上传图片'
})
let a = uni.uploadFile({
url: this.$supervisoryApi + '/file/fileupload', // 上传接口地址,例如:http://127.0.0.1:8080/file/fileupload
filePath: url,
name: 'file',
formData: {
user: 'test'
},
success: (res) => {
uni.$u.toast('上传成功');
resolve(JSON.parse(res.data).url);
},
complete: () => {
uni.hideLoading();
}
});
})
},
//获取当前日期,格式YYYY-MM-DD
getNowFormatDay(nowDate) {
var char = "-";
if(nowDate == null){
nowDate = new Date();
}
var day = nowDate.getDate();
var month = nowDate.getMonth() + 1;//注意月份需要+1
var year = nowDate.getFullYear();
//补全0,并拼接
return year + char + this.completeDate(month) + char + this.completeDate(day);
},
//获取当前时间,格式YYYY-MM-DD HH:mm:ss
getNowFormatTime() {
var nowDate = new Date();
var colon = ":";
var h = nowDate.getHours();
var m = nowDate.getMinutes();
var s = nowDate.getSeconds();
//补全0,并拼接
return this.getNowFormatDay(nowDate) + " " + this.completeDate(h) + colon + this.completeDate(m) + colon + this.completeDate(s);
},
//补全0
completeDate(value) {
return value < 10 ? "0"+value:value;
},
后端接口:/file/fileupload文件上传代码如下
//Controller代码:
@PostMapping("/file/fileupload")
public FileEntity fileupload(@RequestParam("file") MultipartFile file) {
FileEntity fileEntity = fileService.fileupload(file);
return fileEntity;
}
//Servie代码:
FileEntity fileupload(MultipartFile files);
//Service实现类代码:
private String BUCKET_NAME = "aaaaa"; // 自行修改
private String ORIGINAL_NAME = "bb"; // 自行修改
@Override
public FileEntity fileupload(MultipartFile file) {
FileEntity fileEntity = null;
try {
fileEntity = minioUtil.uploadFile(file,BUCKET_NAME,ORIGINAL_NAME);
} catch (Exception e) {
e.printStackTrace();
}
return fileEntity;
}
MinioUtil工具类代码(项目工程相关的pakage路径我用xxx代替了,请自行替换)
package xxx.util;
import xxx.MinioPropertiesConfig;
import xxx.entity.FileEntity;
import io.minio.*;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Slf4j
@Component
public class MinioUtil {
@Autowired
private MinioPropertiesConfig minioProp;
@Autowired
private MinioClient client;
/**
* 创建bucket
*/
public void createBucket(String bucketName) throws Exception{
if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
/**
* 上传文件
*/
public FileEntity uploadFile(MultipartFile file, String bucketName, String OriginalName){
//判断存储桶是否存在 不存在则创建
try {
createBucket(bucketName);
} catch (Exception e) {
e.printStackTrace();
return null;
}
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 存储桶文件名_时间戳.后缀名
assert originalFilename != null && !"".equals(originalFilename);
String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
String format = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
String fileuuid = UUID.randomUUID().toString().replaceAll("-", "");
String objectName = OriginalName+"/"+format + fileuuid + extName;
//开始上传
try {
client.putObject(
PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
} catch (Exception e) {
e.printStackTrace();
return null;
}
String url = minioProp.getEndpoint() + "/" + bucketName + "/" + objectName;
String urlHost = minioProp.getFilHost() + "/" + bucketName + "/" + objectName;
log.info("上传文件成功url :[{}], urlHost :[{}]", url, urlHost);
FileEntity fileEntity = new FileEntity();
fileEntity.setName(originalFilename);
extName = extName.replace(".","");
fileEntity.setType(extName);
fileEntity.setUrl(url);
return fileEntity;
}
/**
* 获取全部bucket
*
* @return
*/
public List<Bucket> getAllBuckets() throws Exception {
return client.listBuckets();
}
/**
* 根据bucketName获取信息
*
* @param bucketName bucket名称
*/
public Optional<Bucket> getBucket(String bucketName) throws Exception {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 根据bucketName删除信息
*
* @param bucketName bucket名称
*/
public void removeBucket(String bucketName) throws Exception {
client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 获取文件外链
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return url
*/
public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
}
/**
* 获取文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @return ⼆进制流
*/
public InputStream getObject(String bucketName, String objectName) throws Exception {
return client.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws
Exception {
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 大小
* @param contextType 类型
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public FileEntity putObject(String bucketName,String OriginalName, String objectName, InputStream stream, long
size, String contextType) throws Exception {
String extName = objectName.substring(objectName.lastIndexOf("."));
String format = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
String fileuuid = UUID.randomUUID().toString().replaceAll("-", "");
objectName = OriginalName+"/"+format + fileuuid + objectName;
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());
String url = minioProp.getEndpoint() + "/" + bucketName + "/" + objectName;
FileEntity fileEntity = new FileEntity();
fileEntity.setName(objectName);
fileEntity.setType(extName);
fileEntity.setUrl(url);
return fileEntity;
}
/**
* 删除文件
*
* @param bucketName bucket名称
* @param objectName ⽂件名称
* @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
*/
public void removeObject(String bucketName, String objectName) throws Exception {
client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
}
MinioPropertiesConfig配置
package xxx.configuration;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "minio") // 这个在项目yml文件中定义属性
public class MinioPropertiesConfig {
/**
* 端点
*/
private String endpoint;
/**
* 用户名
*/
private String accessKey;
/**
* 密码
*/
private String secretKey;
/**
* 桶名称
*/
private String bucketName;
/**
* 域名
*/
private String filHost;
@Bean
public MinioClient minioClient() {
MinioClient minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey,secretKey)
.build();
return minioClient;
}
}
yml配置minio参数
#minio配置
minio:
endpoint: http://xxxx:9000 #对象存储服务的URL,xxxx换为服务器地址,本机为127.0.0.1或局域网ipv4地址
accessKey: minioadmin #Access key账户
secretKey: minioadmin #Secret key密码