回顾昨天的项目需求:
1.视频的上传,查看,点赞,评论,收藏
2.用户的个人模块的完善(包括常见的权限,增删改查这样几个)✔
3.手机号,邮箱的登录注册。✔
4.动态关注,消息提醒这些
5.使用爬虫技术,加上定时任务长期获取数据源✔
6.匹配系统,匹配相似度高的用户✔
ok,再出一期,把下面的的需求给完成以下(其实主要也就是视频模块的东西),顺便再用一些比较有意思的技术试试。
对于视频这种比较大的文件建议使用minio进行对象存储(这里再展示一下minio的使用方式)
在云服务器上面安装mimio
sudo docker run -itd \
--name=minio \
-p 9000:9000 \
-p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
-v /path/to/your/data:/data \
-v /path/to/your/config:/root/.minio \
minio/minio server /data --console-address ":9001"
访问端口号:9001即可,这里设置的账号密码都是minioadmin
进入访问然后创建一个bucketName(取名的时候用小写)
代码操作minio:
引入依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
踩坑:使用
static MinioClient minioClient = MinioClient.builder()
.endpoint("http://xxx.xxx.xxx.xxx:9001")
.credentials("minioadmin","minioadmin")
.build();
这里使用9001无法实现存储。
根据异常信息 S3 API Requests must be made to API port,这表明您的 Minio 服务器配置了一个专用的端口用于处理 S3 API 请求,而您当前使用的端口可能不是正确的 API 端口。
通常情况下,Minio 服务会运行在两个端口上:
API端口:默认为 9000,用于处理 S3 兼容的 API 请求。
控制台端口:默认为 9001,用于 Minio 控制台界面。
您当前使用的端口是 9001,这是用于 Minio 控制台的端口,并不接受 S3 API 请求。因此,您需要将 MinioClient 的 endpoint 修改为正确的 API 端口,通常是 9000。
下面是修改后的代码示例:
@SpringBootTest
public class MinioTest {
static MinioClient minioClient = MinioClient.builder()
.endpoint("http://xxx.xxx.xxx.xxx:9000") // 修改端口为 9000
.credentials("minioadmin", "minioadmin")
.build();
@Test
public void test() {
try {
UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
.bucket("cetide846513")
.object("BigFileTest.java")
.filename("BigFIleTest.java")
.build();
// 在上传之前,确保桶已经存在
if (!minioClient.bucketExists(BucketExistsArgs.of("cetide"))) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket("cetide").build());
}
minioClient.uploadObject(uploadObjectArgs);
System.out.println("上传成功");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
为了使用 com.j256.simplemagic.ContentInfo 和 com.j256.simplemagic.ContentInfoUtil 这两个类,你需要在你的项目中添加 Simple Magic 库的依赖。
Simple Magic 是一个用于检测文件类型的 Java 库,它可以基于文件的内容来确定文件的 MIME 类型。
如果你使用的是 Maven,可以在 pom.xml 文件中添加以下依赖:
<dependencies>
<dependency>
<groupId>com.j256.simplemagic</groupId>
<artifactId>simplemagic</artifactId>
<version>1.2.1</version> <!-- 请替换为最新的版本 -->
</dependency>
</dependencies>
那么开始编写代码:
Controller层
@RestController
public class FileUploadController {
@Autowired
private MediaFileService mediaFileService;
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/upload")
public Result<String> uploadPic(@RequestPart MultipartFile file) throws Exception {
// 生成文件名
String originalFilename = file.getOriginalFilename();
String filename = null;
if (originalFilename != null) {
filename = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
}
// 上传文件
String publicUrl = CosUtils.uploadFile(file, filename);
return Result.success(publicUrl);
}
@ApiOperation("上传图片")
@PostMapping(value = "/upload/course_file",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result<UploadFileResultDto> uploadMedia(@RequestPart("filedata")MultipartFile filedata) throws IOException {
//准备上传文件的信息
UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto();
//原始文件名称
uploadFileParamsDto.setFilename(filedata.getOriginalFilename());
//文件大小
uploadFileParamsDto.setFileSize(filedata.getSize());
//文件类型
uploadFileParamsDto.setFileType("视频");
//设置创建人
User user = (User) redisTemplate.opsForValue().get("user");
uploadFileParamsDto.setUsername(user.getUsername());
//备注和标签从前端获取到
//创建一个临时文件
File tempFile = File.createTempFile("minio", ".temp");
//将上传的文件写到临时文件中
filedata.transferTo(tempFile);
Long companyId = 1232141425L;
//文件路径
String localFilePath = tempFile.getAbsolutePath();
//调用service上传图片
return mediaFileService.uploadFile(companyId, uploadFileParamsDto, localFilePath);
}
}
public PageResult<MediaFiles> queryMediaFiels(Long companyId, PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto);
public Result<UploadFileResultDto> uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath);
public MediaFiles addMediaFilesToDb(Long companyId,String fileMd5,UploadFileParamsDto uploadFileParamsDto,String bucket,String objectName);
private final String bucket_mediafiles = "cetide";
private final String bucket_video = "cetide";
@Override
public PageResult<MediaFiles> queryMediaFiels(Long companyId, PageParams pageParams, QueryMediaParamsDto queryMediaParamsDto) {
//构建查询条件对象
LambdaQueryWrapper<MediaFiles> queryWrapper = new LambdaQueryWrapper<>();
//分页对象
Page<MediaFiles> page = new Page<>(pageParams.getPageNo(), pageParams.getPageSize());
// 查询数据内容获得结果
Page<MediaFiles> pageResult = mediaFilesMapper.selectPage(page, queryWrapper);
// 获取数据列表
List<MediaFiles> list = pageResult.getRecords();
// 获取数据总数
long total = pageResult.getTotal();
// 构建结果集
return new PageResult<>(list, total, pageParams.getPageNo(), pageParams.getPageSize());
}
//根据扩展名获取mimeType
private String getMimeType(String extension){
if(extension == null){
extension = "";
}
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流
if(extensionMatch!=null){
mimeType = extensionMatch.getMimeType();
}
return mimeType;
}
/**
* 将文件上传到minio
* @param localFilePath 文件本地路径
* @param mimeType 媒体类型
* @param bucket 桶
* @param objectName 对象名
* @return
*/
public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName){
try {
UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
.bucket(bucket)//桶
.filename(localFilePath) //指定本地文件路径
.object(objectName)//对象名 放在子目录下
.contentType(mimeType)//设置媒体文件类型
.build();
//上传文件
minioClient.uploadObject(uploadObjectArgs);
// log.debug("上传文件到minio成功,bucket:{},objectName:{},错误信息:{}",bucket,objectName);
return true;
} catch (Exception e) {
e.printStackTrace();
// log.error("上传文件出错,bucket:{},objectName:{},错误信息:{}",bucket,objectName,e.getMessage());
}
return false;
}
//获取文件默认存储目录路径 年/月/日
private String getDefaultFolderPath() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String folder = sdf.format(new Date()).replace("-", "/")+"/";
return folder;
}
//获取文件的md5
private String getFileMd5(File file) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
String fileMd5 = DigestUtils.md5Hex(fileInputStream);
return fileMd5;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
那么,demo项目的功能也基本就能够跑通了。
剩下的就开始前后端联调,然后完善具体的业务方法吧.
此时回到前端:
npm开启,(这里的前端比较简单,vue+ element-ui +vite)
进行文章帖子列表的展示与刷新,随机推送几条数据。
这边就不细讲了,下面来看看如何部署前后端:
后端用云服务器安装宝塔进行部署:
前端的话用vercel进行部署
"build": "vue-tsc -b && vite build",
vite build打包成dist
然后使用vercel --prod