一:前期准备:
1.1:注册阿里云账号,开启对象存储oss功能,创建一个bucket(百度教程多的是,跟着创建一个就行,创建时注意存储类型是标准存储,读写权限是公共读)
二:后端设置:
2.1:引入依赖:
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2.2:在application.yml中配置一些必要的属性,并写一个类读取出来(我是这样使用的,将某些特定的数据都写到application.yml文件中,方便更改,当然你也可以直接将他写在类的代码中,只不过找起来可能麻烦点)
bookstore:
alioss:
endpoint: xxxxx #外网访问的地域节点
access-key-id: xxxxxx #访问阿里云api的秘钥
access-key-secret: xxxxxxx #访问阿里云api的秘钥
bucket-name: xxxxxxxx #bucket-name
//写在application.yml文件中,这些数据在阿里云中可以找到,秘钥在自己的账号主页里创建生成,地域节点和bucket-name都在创建好bucket后查看
读取配置中的数据
package com.bookstore.common.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "bookstore.alioss")
@Data
public class AliOssProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
//读取配置里的相关数据
2.3:封装一个上传图片的工具类,阿里云已经给出了具体代码,没有什么需要修改的内容,直接cv大法就行
package com.bookstore.common.utils;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
/**
* 文件上传
*
* @param bytes
* @param objectName
* @return
*/
public String upload(byte[] bytes, String objectName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
//文件访问路径规则 https://BucketName.Endpoint/ObjectName
StringBuilder stringBuilder = new StringBuilder("https://");
stringBuilder
.append(bucketName)
.append(".")
.append(endpoint)
.append("/")
.append(objectName);
log.info("文件上传到:{}", stringBuilder.toString());
return stringBuilder.toString();
}
}
2.4:写配置类,这个类是来创建AliOssUtil对象并注入到springboot中,就是实例化我们上面封装的那个工具类并将我们上面写的从配置中读取数据的类传进去,最后返回URL路径,它也没有什么需要更改的,cv就行
package com.bookstore.config;
import com.bookstore.common.properties.AliOssProperties;
import com.bookstore.common.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类,用于创建AliOssUtil对象
*/
@Configuration
@Slf4j
public class OssConfiguration {
@Bean
@ConditionalOnMissingBean
public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
return new AliOssUtil(aliOssProperties.getEndpoint(),
aliOssProperties.getAccessKeyId(),
aliOssProperties.getAccessKeySecret(),
aliOssProperties.getBucketName());
}
}
2.5:写一个通用接口,后端上传图片调的就是这个接口,上传一个图片,最后返回文件路径
package com.bookstore.controller.admin;
import com.bookstore.common.constant.MessageConstant;
import com.bookstore.common.result.Result;
import com.bookstore.common.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
/**
* 通用接口
*/
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {
@Autowired
private AliOssUtil aliOssUtil;
/**
* 文件上传
* @param file
* @return
*/
@PostMapping("/upload")
@ApiOperation("文件上传")
public Result<String> upload(MultipartFile file){
log.info("文件上传:{}",file);
try {
//原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件名的后缀.png .jpg
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//构造新文件名称
String objectName = UUID.randomUUID().toString() + extension;
//文件的请求路径
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (IOException e) {
log.error("文件上传失败:{}",e);
}
return Result.error(MessageConstant.UPLOAD_FAILED);
}
}
三:前端怎么写:
前端我使用的是vue框架,代码如下
3.1:模板组件:
<el-form-item label="图片" prop="image">
<el-upload
class="upload-demo"
action="http://localhost:8082/admin/common/upload"
method="post"
:headers="{
token: token,
}"
:on-success="handleUploadSuccess"
:show-file-list="false"
list-type="picture-card"
>
<img
v-if="previewImage"
:src="previewImage"
style="width: 100%; height: 100%"
/>
<i class="el-icon-plus avatar-uploader-icon" v-else></i>
</el-upload>
</el-form-item>
3.1.1:代码解释:
action:这里写的是我们上面的那个通用接口路径
method:使用post(后端就是使用的post方法)
:headers:这里用来设置请求头,我在请求头上添加了一个token用来校验用户
:on-success:这里是上传成功的回调函数
:show-file-list:设置是否显示文件列表
list-type="picture-card":设置上传文件列表的样式为图片卡片形式。图片卡片形式可以让用户更直观地看到上传的图片,并且可以方便地进行删除或替换操作。
下面的img组件和i标签组件我使用了v-if和v-else来显示上传成功后的样子(是上传之前的图标还是上传成功后的图片回显)
3.2:script的data里写:
data(){
return{
token: "", //请求头
previewImage: "", // 图片回显
}
}
3.3:script的方法中写好图片上传成功后的回调函数
handleUploadSuccess(response) {
// 图片上传成功后的回调函数
console.log(response.data);
this.previewImage = response.data; // 设置图片回显
},
四:运行效果:
4.1:上传图片之前:
4.2:上传图片后:
4.3:后端控制台打印消息提示:
可以看到,运行成功,一切正常,而且我们的bucket里也是正常有图片的