uniapp + uview实现图片上传minio全过程实现,并对图片做了加水印

该博客详细介绍了在前端页面使用uView UI库的u-upload组件进行图片上传,结合uni-app实现图片预览、添加水印及限制上传数量。在后端,使用MinIO作为文件存储服务,实现了文件上传接口,包括创建bucket、上传文件、获取文件外链等功能。此外,还展示了如何配置MinIO的相关参数和YAML配置。
摘要由CSDN通过智能技术生成

在前端页面中,采用了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密码
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
迷你图片批量处理工具,她能够帮您迅速大批量处理您的图片。您只需要将一张或多张图片甚至一个文件夹拖放到添窗口,即可完成图片的添,方便好用。 功能概述:批量更改大小、批量图片压缩、批量添水印、批量更改格式、批量增特效等。 修订概述: 新增水印图片旋转功能。 新增图片旋转、灰色、反色、模糊、锐化、棕色、红色、绿色、蓝色、青色、品红、黄色等特效处理。 新增图片色相、饱和度、亮度、对比度、阀值等调整功能。 新增以文件名、拍摄时间、当前时间为水印文字的设置。 新增水印文字与水印图片的同时支持。 新增图片裁剪的自定义裁剪位置。 新增添水印时对小尺寸图片的过滤功能。 新增设置保存功能。 新增水印图片输入框拖拽功能,您可以直接将水印图片拖拽至水印图片文本框。 修正了多文件夹拖拽到添图片窗体后出现的程序崩溃问题。 修订了图片修改后EXIF信息丢失的问题。 新增图片列表Delete快捷键移除图片功能。 提示:如果您不能正常使用该软件,请安装.NET Framework 2.0, 下载地址:http://www.microsoft.com/downloads/details.aspx?familyid=0856EACB-4362-4B0D-8EDD-AAB15C5E04F5&displaylang=zh-cn 迷你软件系列工具: 迷你图片批量处理工具 迷你文件校验工具 迷你定时提醒工具 迷你词典(MiniDict) Excel数据导出工具 迷你网站检测工具 迷你批量更改文件编码工具 ... 、
NestJS是一个基于Node.js的开发框架,它提供了许多有用的功能和工具,其中包括对Minio的支持。Minio是一个开源的对象存储服务器,它兼容Amazon S3 API,可以用于存储和检索大量数据。在NestJS中引入Minio可以通过安装minio-js库来实现。在NestJS中使用Minio需要创建一个MinioService类,该类需要使用minio-js库中的Minio.Client类来连接到Minio服务器。在MinioService类中,可以使用putObject方法将文件上传到Minio服务器。在上传文件之前,需要对已有的文件进行判断是否有相同文件名(或者使用时间戳),如果有重名的文件会对其进行覆盖操作。下面是一个示例代码,用于在NestJS中引入Minio: // minio.service.ts import { Injectable } from "@nestjs/common"; import * as Minio from "minio"; @Injectable() export class MinioService { private readonly minioClient: Minio.Client; constructor() { this.minioClient = new Minio.Client({ // 服务ip endPoint: "192.168.18.24", // 服务端口 port: 9000, useSSL: false, accessKey: "minioadmin", secretKey: "minioadmin", }); } async uploadFile(bucketName: string, objectName: string, stream: Buffer) { const res = await this.minioClient.bucketExists(bucketName); console.log(res); console.log(objectName, stream); await this.minioClient.putObject( bucketName, objectName, stream, function (e) { if (e) { console.log(e); return "error"; } else { // 如果重名也会成功 return "Successfully uploaded the buffer"; } }, ); } } --相关问题--: 1. Minio和Amazon S3有什么区别? 2. NestJS还支持哪些对象存储服务器? 3.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值