后台代码
@RestController
@RequestMapping("/brand")
public class BrandController {
@Autowired
private IBrandService bs;
@PostMapping("/uploadPic")
//文件上传的方法,上传成功后需要把文件上传到哪交给前端
public String uploadPic(MultipartFile brandPic) throws IOException {
//把图片保存起来。一般情况下我们会专门创建一个文件夹来保存上传的图片
String oldName=brandPic.getOriginalFilename();//获取到上传的文件的原始文件名
String newName = UUID.randomUUID().toString()+oldName;
File targetFile=new File("d:/uploadImg/"+newName);
brandPic.transferTo(targetFile);//把图片复制到某个位置
return newName;
}
}
文件上传成功后可以通过URL访问到图片:
spring:
resources:
static-locations: file:D:\myImg
访问的路径是:http://ip:port/appName/图片名称
文件存储的常用方式
保存在当前服务器中 优点:简单 缺点:
通过第三方文件存储技术 FastDFS MinIO
对象存储服务 指的就是文件存储 例如:视频 文件 音频图片等
优点:可以根据自己的需求灵活定制
缺点:
使用阿里云 亚马逊 百度等公司提供OSS服务(对象存储服务) 中小型企业 优点:简单快速,成本低
<dependency>
<groupId>com.aliyun.ossgroupId>
<artifactId>aliyun-sdk-ossartifactId>
<version>3.10.2version>
dependency>
public class OSSTest {
public static void main(String[] args) throws FileNotFoundException {
//1. 创建连接
// Endpoint以北京为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
// 这里填写上面获取的 accessKeyId、 accessKeySecret
String accessKeyId="xxxxx";
String accessKeySecret = "xxx";
OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//2. 通过client发起上传文件的请求
String bulkName ="bz-mall-admin2";
String key=UUID.randomUUID().toString()+"git-bash.png"; //文件的唯一标识,通常是不重复的文件名
InputStream in = new FileInputStream("D:/git-bash.png");
// 上传文件到指定的存储空间(bucketName)并将其保存为指定的文件名称(key)。
client.putObject(bulkName, key, in);
//3. 关闭连接
client.shutdown();
// https://bulkName+"."+endpoint+"/"+key 就是文件的外网访问路径
// https://bz-mall-admin.oss-cn-beijing.aliyuncs.com/拼接了uuid的文件名
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7669LQco-1659523644686)(D:\课件\Java\百知\javaEE\后期项目\后期项目OSS\format_webp (15)].jpg)
package com.qhx.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
public class OSSUtils {
/**
* 这里填写自己的accesskeyId和secret,尽量使用子账号的。主账号的权限太高
*/
private static String ACCESSKEYID = "xxxx";
private static String SECRET = "xxxxx";
public static String upload(String filename,InputStream inputStream){
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-hangzhou.aliyuncs.com";
// bucketName
String bucketName = "yingxue-api-qhx";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESSKEYID, SECRET);
// 填写Bucket名称,例如examplebucket。
// 填写文件名。文件名包含路径,不包含Bucket名称。例如exampledir/exampleobject.txt。
ossClient.putObject(bucketName, filename, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
// 返回了视频的访问路径
return "https://" + bucketName + "." + endpoint + "/" + filename;
}
// 上传文件 参数是file,可以是图片、视频等
public static String upload(MultipartFile file) throws IOException {
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-hangzhou.aliyuncs.com";
// bucketName
String bucketName = "yingxue-api-qhx";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESSKEYID, SECRET);
// 获取文件原始名称
String originalFileName = file.getOriginalFilename();
// 获取文件后缀
String ext = FilenameUtils.getExtension(originalFileName);
// 生成uuid并去除-
String uuidFileName = UUID.randomUUID().toString().replace("-","");
// 生成uuid文件名名称
String newFileName = uuidFileName + "." + ext;
// 获取流
InputStream in = file.getInputStream();
// 填写文件名。文件名包含路径,不包含Bucket名称。例如exampledir/exampleobject.txt。
ossClient.putObject(bucketName,newFileName, in);
// 关闭OSSClient。
ossClient.shutdown();
System.out.println("新文件名为:" + newFileName);
System.out.println("访问路径:"+"https://" + bucketName + "." + endpoint + "/" + newFileName);
// 返回了视频的访问路径
return "https://" + bucketName + "." + endpoint + "/" + newFileName;
}
// 视频获取封面 随机截取一帧当封面
public static String getCover(String url){
return url + "?x-oss-process=video/snapshot,t_30000,f_jpg,w_0,h_0,m_fast,ar_auto";
}
}
@PostMapping("/user/videos")
public Video uploadFile(MultipartFile file,
@RequestParam("title") String title,@RequestParam("intro") String intro,
@RequestParam("category_id")Integer cid,HttpServletRequest request) throws Exception{
String bucketName = "yingxue-api-qhx";
// 获取文件原始名称
String originalFileName = file.getOriginalFilename();
log.info("接收文件名称:"+originalFileName);
log.info("接受视频信息:title="+title+" intro="+intro+" cid="+cid);
log.info("类别id:"+cid);
log.info("文件大小:"+file.getSize());
String url = OSSUtils.upload(file);
// 阿里云oss截取视频某一帧作为封面
String cover = OSSUtils.getCover(url);
log.info("封面地址:"+cover);
// 设置视频信息
Video newvideo = new Video();
newvideo.setCover(cover); // 封面地址
newvideo.setCategoryId(cid); // 类别id
newvideo.setTitle(title); // 视频标题
newvideo.setIntro(intro); // 视频简介
newvideo.setLink(url); // 视频地址
newvideo.setCreatedAt(LocalDateTime.now());
newvideo.setUpdatedAt(LocalDateTime.now());
// 获取用户信息
User user = (User) request.getAttribute("user");
newvideo.setUid(user.getId()); // uid
newvideo.setLikes(0); // 点赞数
// 添加视频
Video resultVideo = videoClient.publish(newvideo);
return resultVideo;
}
MinIO是一个基于Apache License v2.0开源协议的对象存储服务。非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据等,而一个对象文件可以是任意大小,从几kb到最大5T不等。MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服 务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成 本。
对于中小型企业,如果不选择存储上云,那么 Minio 是个不错的选择,麻雀虽小,五脏俱全。
#安装wget
yum install -y wget
# 使用wget下载minio可执行文件
wget -P /opt http://dl.minio.org.cn/server/minio/release/linux-amd64/minio
chmod +x minio
#启动minio server服务,指定数据存储目录/mnt/data
./minio server /mnt/data
默认用户名密码minioadmin:minioadmin,修改默认用户名密码可以使用:
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=12345678
控制台监听端口是动态生成的,可以通过–console-address ":port"指定静态端口
./minio server --console-address ":50000" /mnt/data
访问minio控制台: http://192.168.239.105:50000/dashboard
MinIO Client (mc)为ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案。
wget http://dl.minio.org.cn/client/mc/release/linux-amd64/mc
chmod +x mc
mv mc /usr/local/sbin/
# 查询mc host配置
mc config host ls
# 添加minio服务
mc config host add host名称 http://192.168.239.105:9000 账号 密码
# 删除host
mc config host remove host名称
# 查询minio服务上的所有buckets(文件和文件夹)
mc ls host名称
#上传文件
mc cp 上面文件地址 host名称/bucket名称/
# 下载文件
mc cp minio-server/mydir/fox/fox.jpg /tmp/
#删除文件
mc rm minio-server/mydir/fox/fox.jpg
# 创建bucket
mc mb minio-server/bucket01
# 删除bucket
mc rb minio-server/bucket02
# bucket不为空,可以强制删除 慎用
mc rb --force minio-server/bucket01
#查询bucket03磁盘使用情况
mc du minio-server/bucket03
mc admin user --help
#新建用户
mc admin user add minio-server fox
mc admin user add minio-server fox02 12345678
#查看用户
mc admin user list minio-server
#禁用用户
mc admin user disable minio-server fox02
#启用用户
mc admin user enable minio-server fox02
#查看用户信息
mc admin user info minio-server fox
#删除用户
mc admin user remove minio-server fox02
#列出MinIO上的所有固定策略
mc admin policy list minio-server
# 查看plicy信息
mc admin policy info minio-server readwrite
编写策略文件:/root/baizhi.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::host名字"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::host名字/*"
]
}
]
}
"Action": [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
]
将baizhi.json添加到策略数据库
# 添加新的策略
mc admin policy add minio-server baizhi-admin /root/baizhi.json
mc admin policy list minio-server
mc admin user add minio-server fox03 12345678
# 设置用户的访问策略
mc admin policy set minio-server baizhi-admin user=fox03
测试:fox03/12345678 登录minio控制台http://192.168.3.14:50000/,只能操作baizhihost的bucket
<dependency>
<groupId>io.miniogroupId>
<artifactId>minioartifactId>
<version>8.3.0version>
dependency>
<dependency>
<groupId>me.tongfeigroupId>
<artifactId>progressbarartifactId>
<version>0.5.3version>
dependency>
<dependency>
<groupId>com.squareup.okhttp3groupId>
<artifactId>okhttpartifactId>
<version>4.8.1version>
dependency>
<dependency>
<groupId>org.jetbrains.kotlingroupId>
<artifactId>kotlin-stdlibartifactId>
<version>1.3.70version>
dependency>
@Test
public void testUpload()
throws IOException, NoSuchAlgorithmException, InvalidKeyException {
try {
// Create a minioClient with the MinIO server playground, its access key and secret key.
MinioClient minioClient = MinioClient
.builder()
.endpoint("http://192.168.239.106:9000")
.credentials("zhangsan", "12345678")
.build();
// 创建bucket
String bucketName = "bzmall-2015";
// 上传文件
minioClient.uploadObject(UploadObjectArgs.builder()
.bucket(bucketName)
.object("test.png")
.filename("D:\\test.png")
.build());
System.out.println("上传文件成功");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
System.out.println("HTTP trace: " + e.httpTrace());
}
}
@Test
public void testDownload() {
// Create a minioClient with the MinIO server playground, its access key and secret key.
MinioClient minioClient = MinioClient
.builder()
.endpoint("http://192.168.239.106:9000")
.credentials("zhangsan", "12345678")
.build();
// Download object given the bucket, object name and output file name
try {
minioClient.downloadObject(DownloadObjectArgs
.builder().bucket("bzmall-2015")
.object("test.png")
.filename("d://test2.png")
.build());
} catch (Exception e) {
e.printStackTrace();
}
}
构建MinioClient对象,并交给spring管理
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
yml文件:
//yml
minio:
endpoint: http://192.168.3.14:9000
accesskey: admin
secretKey: 12345678
读取配置文件的类:
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
private String endpoint;
private String accessKey;
private String secretKey;
}
配置类:
@Configuration
public class MinioConfig {
@Autowired
private MinioProperties minioProperties;
@Bean
public MinioClient minioClient() {
MinioClient minioClient = MinioClient.builder()
.endpoint(minioProperties.getEndpoint())
.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
.build();
return minioClient;
}
}
文件上传:
@Autowired
private MinioClient minioClient;
@Value("${minio.bucketName}")
private String bucketName;
@Value("${minio.endpoint}")
private String endpoint;
@PostMapping("/uploadPic")
//文件上传的方法,上传成功后需要把文件上传到哪交给前端
public ResultEntity uploadPic(MultipartFile brandPic) throws IOException {
String orgfileName = brandPic.getOriginalFilename();
String newName= UUID.randomUUID().toString()+orgfileName;
try {
//文件上传
InputStream in = brandPic.getInputStream();
minioClient.putObject(PutObjectArgs
.builder()
.bucket(bucketName)
.object(newName)
.stream(in, brandPic.getSize(), -1)
.contentType(brandPic.getContentType())
.build());
in.close();
} catch (Exception e) {
return ResultEntity.error("上传失败");
}
return ResultEntity.ok(endpoint+"/"+bucketName+"/"+newName);
}
文件下载:
@GetMapping("/download/{fileName}")
public void download(HttpServletResponse response,
@PathVariable("fileName") String fileName) throws IOException {
InputStream in = null;
try {
// 获取对象信息
StatObjectResponse stat = minioClient.statObject(StatObjectArgs.
builder().
bucket(bucketName).
object(fileName).
build());
response.setContentType(stat.contentType());
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
//文件下载
in = minioClient.getObject(
GetObjectArgs.
builder().
bucket(bucketName).
object(fileName).
build());
IOUtils.copy(in, response.getOutputStream());
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
object(fileName).
build());
response.setContentType(stat.contentType());
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
//文件下载
in = minioClient.getObject(
GetObjectArgs.
builder().
bucket(bucketName).
object(fileName).
build());
IOUtils.copy(in, response.getOutputStream());
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}