java minio通过getPresignedObjectUrl设置(自定义)预签名URL下载文件的响应文件名之minio源码改造方案

需求说明

用户上传文件到Minio时,一般存储在Minio中的对象名称都是后端以UUID或者其他随机或非随机方案生成的唯一标识做为文件名,这个对象名称一般都不会是用户上传时的原文件名称。

在用户下载时,想让文件流不通过后端服务器,而是用户直接申请并使用某个要下载对象的Minio预签名的url,直接从Minio所部署的服务器下载该文件。

但是浏览器通过预签名的url下载文件时,由于无法自定义Minio下载文件的请求响应头中的文件名称,所以在浏览器下载时,保存的文件名是以对象名称进行保存的,那么这个文件名是对用户感知等都是不友好的。

所以需要根据预签名url下载文件(我这里是用GET)请求中的filename参数,把响应头的Content-Disposition内容上指定文件名称

注:本方案是修改Minio源代码实现该功能,因为Minio好像没有实现这个功能

Minio源码改造

一、环境准备

这里大家自己百度查询相关教程

  • Go语言环境,并设置好Go的依赖下载代理
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
  • GoLand编辑器(当然用别的也行)

我使用的go版本:go version go1.21.0 linux/amd64

二、下载Minio源代码

使用git下载

git clone https://github.com/minio/minio.git

三、修改源代码

1.修改cmd目录下的api-router.go这个代码文件

搜索改文件内容:GetObjectHandler
在这里插入图片描述

进入api.GetObjectHandler这个handler查看代码,在这个函数前面加上一个自定义的函数GetUrlArgs,这个函数的功能是获取GET请求url中的某个参数值

/**
获取URL的get参数
*/
func GetUrlArgs(r *http.Request, name string) string {
	var arg string
	values := r.URL.Query()
	arg = values.Get(name)
	return arg
}

在这里插入图片描述

2.将filename参数值设置到响应头

在这个函数里面,添加这段代码,作用是将请求url中的filename参数值设置到响应头的Content-Disposition中

	// 将filename参数值添加到响应头做为响应名
	var filename string = GetUrlArgs(r, "filename")
	if filename != "" {
		// 该写法可以解决中文文件名乱码问题
		w.Header().Set("Content-Disposition", 
			fmt.Sprintf("attachment; filename*=UTF-8''%s", url.QueryEscape(filename)))
	}

在这里插入图片描述

4.修改验证签名时是否需要带入filename参数验证

如果你在获取预签名url时,就携带了filename参数,就不用做这一步了,那么这个预签名url的任何参数值都是不能被更改的,包括filename。

例如我的java minio客户端获取预签名url代码:

		Map<String, String> query = new HashMap<>(2, 1);
        query.put("filename", responseFileName);
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)  // 对象名称
                .expiry(10, TimeUnit.SECONDS) // 该url签名10秒过期
                .method(Method.GET)  // 该url允许的请求方式
                .extraQueryParams(query) // 把filename加在查询字符串上
                .build();
        // 创建预签名url
        String preSignedObjectUrl = minioClient.getPresignedObjectUrl(args);

如果你在获取预签名url时根本就没有携带上filename进行url预签名,而是想让前端或者请求者在url上加上filename=xxx这个参数,文件名可以随便由请求者设置,那么就需要修改Minio源码中的验证签名操作,让filename这个参数不参与到验证签名中。

例如这是java minio客户端不带filename参数创建预签名url的代码:

        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)  // 对象名称
                .expiry(10, TimeUnit.SECONDS) // 该url签名10秒过期
                .method(Method.GET)  // 该url允许的请求方式
                .build();
        // 创建预签名url
        String preSignedObjectUrl = minioClient.getPresignedObjectUrl(args);

修改Minio源码不让filename参与到验证签名的操作步骤:
代码文件:cmd/signature-v4.go
搜索函数:doesPresignedSignatureMatch
在该函数的这个循环中,修改这个循环,判断条件中加入参数k不是filename的条件即可,加入的是图中红色方框这里的代码

	//Add missing query parameters if any provided in the request URL
	for k, v := range req.Form {
		if !defaultSigParams.Contains(k) && k != "filename" {
			query[k] = v
		}
	}

在这里插入图片描述

四、大功告成,编译go代码生成可执行文件

按需执行以下命令,下载好相关依赖之后,就会编译生成一个可执行文件minio,当然这个可执行文件名可以在命令中修改,打包之后,这个可执行文件就是可以和官方下载的可执行文件一样运行了,依旧按照官方的文档使用。

本机运行打包命令
go build main.go
ARM打包命令
# CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o 可执行文件名 main.go
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o minio main.go
AMD打包命令
# CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o 可执行文件名 main.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o minio main.go

五、使用预签名URL下载文件测试

我获取预签名url是设置的filename是a.txt,存储在Minio中是一大长串xxxxxx.txt,浏览器保存的文件名也是a.txt。如果是中文名的话会自动进行编码后响应,浏览器能自动转码为中文文件名进行保存。
在这里插入图片描述

  • 31
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要通过Java代码实现通过网络URL路径上传文件MinIO,您可以使用`putObject`方法和`url`参数。下面是一个示例代码: ```java import io.minio.*; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; import java.net.URL; public class MinioUploader { private static final String ENDPOINT = "http://localhost:9000"; private static final String ACCESS_KEY = "ACCESS_KEY"; private static final String SECRET_KEY = "SECRET_KEY"; public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InvalidKeyException { MinioClient minioClient = MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY, SECRET_KEY) .build(); String bucketName = "my-bucket"; String objectName = "my-object"; URL url = new URL("http://example.com/my-file.txt"); PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(url.openStream(), -1, 10485760) .build(); minioClient.putObject(putObjectArgs); System.out.println("File uploaded successfully"); } } ``` 请注意,`stream`方法用于从URL打开的输入流中读取文件内容。`-1`表示未知文件大小,`10485760`表示上传块大小(10 MB)。 此外,您需要将`bucketName`和`objectName`更改为您自己的值,以及将`url`更改为您想要上传的文件URL路径。 这就是通过网络URL路径上传文件MinIO的基本步骤。您可以根据需要调整代码和参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值