阿里云OSS无法使用图片URL访问,访问时提示下载【已解决】
阿里云OSS无法使用图片URL访问,访问时提示下载【已解决】_JGYBZX_G的博客-CSDN博客_oss 访问图片
实现图片上传到oss,解决阿里云OSS无法使用图片URL访问,访问时提示下载,不用申请域名。
简单图片上传
实现图片上传到oss,解决阿里云OSS无法使用图片URL访问,访问时提示下载,不用申请域名。
创建 Bucket
建立RAM账号 链接: [官方文档](https://help.aliyun.com/document_detail/93720.html).
根据官方文档 编写简单上传
填坑环节
二次修改
修改文件太大,spring报错的问题
三次修改
关于返回路径的问题
创建 Bucket
右上方选择创建 Bucket,可以看到下方有很多常用入口
创建 一般选择默认即可,注意命名规范,此时留意一下读写权限,后边有个坑
右上角点击 bucket列表 可以查看
建立RAM账号 链接: 官方文档.
官方提示 建立RAM账号,因为自己的账号权限太大一旦泄露,就会出现问题,所以需要建立RAM账号,相当于子账号,然后给子账号分配权限,比如本次是实现对象存储。
创建用户。注意选择编程式访问,用于程序访问
返回用户列表,点击用户进入设置用户。
创建 AccessKey,及时记录下来,如果忘记了,可以重新创建
添加权限(此处指OSS权限)
根据官方文档 编写简单上传
用的是先保存到本地然后以文件流的形式上传到OSS,上传方式很多种,这是最简单的
1
controller
@PostMapping("/fileUpload.json")
public String fileUpload(@RequestParam("file") MultipartFile file) throws FileNotFoundException {
if (file.isEmpty()) {
return "上传文件内容为空,请重新选择";
}
String tempFilePath = this.getClass().getResource("/").getPath();
String fileName = file.getOriginalFilename();
File tempFile = new File(tempFilePath + fileName);
try {
file.transferTo(tempFile);
//return "上传成功" + tempFilePath + fileName;
} catch (IOException e) {
e.printStackTrace();
}
return ossConfig.fileUpload(fileName, tempFilePath + fileName);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.jgybzx.config;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author jgybzx
* @date 2020/12/21 15:40
* @description 用于连接阿里 OSS 对象存储的必要条件,放在配置文件中,以ConfigurationProperties方式读取
*/
@Component
@ConfigurationProperties(prefix = "oss")
public class OssConfig {
/**
* 使用自己真实的地址
*/
private String endpoint;
/**
* 之前复制的 accessKeyId
*/
private String accessKeyId;
/**
* 之前复制的 accessKeySecret
*/
private String accessKeySecret;
/**
* 自己新建的 bucketName
*/
private String bucketName;
/**
* @param fileName 文件上传时的名字
* @param tempFilePath 文件保存到本地时的临时目录,用于生产文件流
* @return
* @throws FileNotFoundException
*/
public String fileUpload(String fileName, String tempFilePath) throws FileNotFoundException {
// 用于在OSS上命名,建议格式 :年月日/文件名.后缀名,此时可以 以时间建立一个文件夹保存上传的图片
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String transformDate = simpleDateFormat.format(new Date());
String objectName = transformDate + "/" + System.currentTimeMillis() + "_" + fileName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 上传文件流。
InputStream inputStream = new FileInputStream(tempFilePath);
ossClient.putObject(bucketName, objectName, inputStream);
// 返回一个带有时间限制的 访问连接,(此处坑很大)
Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
String url = ossClient.generatePresignedUrl(bucketName, objectName, expiration).toString();
// 关闭OSSClient。
ossClient.shutdown();
return url.split("\\?")[0];
}
/*省略get set*/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
结果展示
填坑环节
文件正常上传,但是返回的地址无法直接访问,一打开就是下载。
经过百度,出现各种方法,比如映射自己的域名、添加Content-Disposition inline 关键字。标题所示,这个方法不用申请域名,并且不用设置 HTTP头。首先出现让直接下载的情况,怀疑是因为Content-Type = image/jpeg 如果换为 image/jpg 则可以直接预览。
所以解决方法为 代码中设置 Content-Type 参考链接
所以代码进行改动
/**
* @param fileName 文件上传时的名字
* @param tempFilePath 文件保存到本地时的临时目录,用于生产文件流
* @return
* @throws FileNotFoundException
*/
public String fileUpload(String fileName, String tempFilePath) throws FileNotFoundException {
// 用于在OSS上命名,建议格式 :年月日/文件名.后缀名,此时可以 以时间建立一个文件夹保存上传的图片
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String transformDate = simpleDateFormat.format(new Date());
String objectName = transformDate + "/" + System.currentTimeMillis() + "_" + fileName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 设置设置 HTTP 头 里边的 Content-Type
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
// 上传文件流。
InputStream inputStream = new FileInputStream(tempFilePath);
//ossClient.putObject(bucketName, objectName, inputStream);
ossClient.putObject(bucketName, objectName, inputStream, objectMetadata);
// 返回一个有时间的链接,
Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
String url = ossClient.generatePresignedUrl(bucketName, objectName, expiration).toString();
// 关闭OSSClient。
ossClient.shutdown();
return url.split("\\?")[0];
}
/**
* 解决问题,直接访问上传的图片地址,会让下载而不是直接访问
* 设置设置 HTTP 头 里边的 Content-Type
* txt 格式经过测试,不需要转换 上传之后就是 text/plain。其他未测试
* 已知 如果 Content-Type = .jpeg 访问地址会直接下载,本方法也是解决此问题
* @param FilenameExtension
* @return
*/
public static String getcontentType(String FilenameExtension) {
if (FilenameExtension.equalsIgnoreCase(".bmp")) {
return "image/bmp";
}
if (FilenameExtension.equalsIgnoreCase(".gif")) {
return "image/gif";
}
if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
FilenameExtension.equalsIgnoreCase(".jpg") ||
FilenameExtension.equalsIgnoreCase(".png")) {
return "image/jpg";
}
if (FilenameExtension.equalsIgnoreCase(".html")) {
return "text/html";
}
if (FilenameExtension.equalsIgnoreCase(".txt")) {
return "text/plain";
}
if (FilenameExtension.equalsIgnoreCase(".vsd")) {
return "application/vnd.visio";
}
if (FilenameExtension.equalsIgnoreCase(".pptx") ||
FilenameExtension.equalsIgnoreCase(".ppt")) {
return "application/vnd.ms-powerpoint";
}
if (FilenameExtension.equalsIgnoreCase(".docx") ||
FilenameExtension.equalsIgnoreCase(".doc")) {
return "application/msword";
}
if (FilenameExtension.equalsIgnoreCase(".xml")) {
return "text/xml";
}
return "image/jpg";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
各种百度之后,访问还是不行,经过思索发现需要设置 Bucket 读写权限
之前创建Bucket的时候 设置的读写权限为 私有,所以需要设置为 “公共读”,上传的图片默认继承Bucket的权限
终极大坑。
进过以上步骤发现还是不能访问,一直要权限,经过了各种搜索无果,思考了整个过程,发现有一步建立RAM账号很特殊。在设置权限的时候发现下边有一个
Bucket 授权策略
Bucket Policy 是阿里云 OSS 推出的针对 Bucket 的授权策略,您可以通过 Bucket Policy 授权您的 RAM 子账号,或其他用户的 RAM 子账号,访问您的 Bucket 的指定资源,并限制访问来源等。
此时问题可能就找到原因了,此时的Bucket访问是用RAM,所以需要对RAM设置授权策略
二次修改
修改文件太大,spring报错的问题
Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (216185201) exceeds the configured maximum (104857600)
1
配置文件添加配置
properties写法
spring.servlet.multipart.max-file-size=500MB
spring.servlet.multipart.max-request-size=500MB
1
2
yml 写法
spring:
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
1
2
3
4
5
三次修改
关于返回路径的问题
原来是 调用了ossClient.generatePresignedUrl返回了一个地址,后来发现阿里提供了访问的方法,如果文件的读写权限ACL为公共读,即该文件允许匿名访问,那么文件URL的格式为https://BucketName.Endpoint/ObjectName
所以只需要修改一下返回值即可
————————————————
版权声明:本文为CSDN博主「JGYBZX_G」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/JGYBZX_G/article/details/111480067