回顾昨天的项目需求:
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>
踩坑:使用
java">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。
下面是修改后的代码示例:
java">@SpringBootTest
public class MinioTest {static MinioClient minioClient = MinioClient.builder().endpoint("http://xxx.xxx.xxx.xxx:9000") // 修改端口为 9000.credentials("minioadmin", "minioadmin").build();@Testpublic 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层
java">@RestController
public class FileUploadController {@Autowiredprivate MediaFileService mediaFileService;@Autowiredprivate 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);}}
java"> 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);
java">private final String bucket_mediafiles = "cetide";private final String bucket_video = "cetide";@Overridepublic 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());}//根据扩展名获取mimeTypeprivate String getMimeType(String extension){if(extension == null){extension = "";}//根据扩展名取出mimeTypeContentInfo 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;}//获取文件的md5private 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