Преглед изворни кода

新增缩略图
新增迁移oss图片接口

fangzhen пре 3 месеци
родитељ
комит
defdb48f55

+ 130 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -1,6 +1,7 @@
 package com.ruoyi.web.controller.common;
 
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
@@ -12,16 +13,25 @@ import com.ruoyi.common.utils.file.FileUtils;
 import com.ruoyi.common.utils.file.ImageUtils;
 import com.ruoyi.common.utils.file.OssUtils;
 import com.ruoyi.framework.config.ServerConfig;
+import com.ruoyi.generator.domain.Community.CommunityArticleImages;
+import com.ruoyi.generator.mapper.community.CommunityArticleImagesMapper;
+import org.apache.commons.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+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 javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.File;
+import java.io.*;
+import java.net.URL;
+import java.net.URLEncoder;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
@@ -44,6 +54,9 @@ public class CommonController {
 
     private static final String fileUrl = "http://file.iciyuanshidai.com";
 
+    @Resource
+    private CommunityArticleImagesMapper communityArticleImagesMapper;
+
     /**
      * 通用下载请求
      *
@@ -139,6 +152,7 @@ public class CommonController {
             System.out.println(fileName);
             String fileNameResult = fileName.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl);
             String thumbnailPath = "";
+            String compressedFileUrl = "";
 
             if ("video".equalsIgnoreCase(fileType) && waterMark) {
                 String tempThumbnailFile = System.getProperty("java.io.tmpdir") + File.separator + "thumbnail.jpg";
@@ -161,7 +175,10 @@ public class CommonController {
                 // 下载源文件到本地临时目录
                 String tempSourceFile = System.getProperty("java.io.tmpdir") + File.separator + "source_" + FileUtils.getName(fileName);
                 OssUtils.downloadFile(fileName.replace("https://cysd.oss-cn-shanghai.aliyuncs.com/", ""), tempSourceFile);
-
+                //缩略图上传
+                String compressedFile = System.getProperty("java.io.tmpdir") + File.separator + "compress_" + FileUtils.getName(fileName);
+                ImageUtils.compressAndGenerateThumbnail(tempSourceFile, compressedFile, 500, 350, 0.8f);
+                compressedFileUrl = OssUtils.uploadFile(compressedFile);
                 // 本地临时水印文件路径
                 String tempWatermarkFile = System.getProperty("java.io.tmpdir") + File.separator + "watermark_" + FileUtils.getName(fileName);
                 // 添加水印
@@ -177,16 +194,19 @@ public class CommonController {
 
                 // 删除临时文件
                 new File(tempSourceFile).delete();
+                new File(compressedFile).delete();
                 new File(tempWatermarkFile).delete();
             }
 
             fileNameResult = fileNameResult.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl);
+            compressedFileUrl = compressedFileUrl.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl);
             String url = fileNameResult;
             AjaxResult ajax = AjaxResult.success();
             ajax.put("url", url);
             ajax.put("fileName", fileNameResult);
             ajax.put("newFileName", FileUtils.getName(fileNameResult));
             ajax.put("originalFilename", file.getOriginalFilename());
+            ajax.put("compressedFileUrl", compressedFileUrl);
             ajax.put("fileType", fileType);
             ajax.put("thumbnailPath", thumbnailPath.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl));
             return ajax;
@@ -195,6 +215,113 @@ public class CommonController {
         }
     }
 
+
+    @PostMapping("/change")
+    public AjaxResult changeMethod() throws Exception {
+        // 1. 取出图片
+        List<CommunityArticleImages> images = communityArticleImagesMapper.selectList(new QueryWrapper<CommunityArticleImages>()
+                .isNotNull("image_url")
+                .like("image_url","47.122.10.161:8084"));
+
+        for (CommunityArticleImages image : images) {
+            // 2. 对URL中的路径部分进行编码
+            String imageUrl = image.getImageUrl();
+            if (imageUrl.contains(".mp4")) {
+                continue;
+            }
+            String encodedImageUrl = encodeUrl(imageUrl); // 编码 URL 路径部分
+
+            // 3. 获取文件类型(图片、音频、视频等)
+            String fileType = FileUtils.getFileTypeFromUrl(encodedImageUrl);
+
+            // 根据文件类型处理
+            String tempUrl = "";
+            if ("image".equals(fileType)) {
+                // 处理图片
+                tempUrl = processImage(encodedImageUrl, image);
+            } else {
+                // 如果不是图片,跳过处理
+                System.out.println("Skipping non-image file: " + imageUrl);
+            }
+            //如果是服务器图片,则更新图片信息
+            if (imageUrl.contains("47.122.10.161:8084")) {
+                String resultUrl = OssUtils.uploadFile(tempUrl);
+                image.setImageUrl(resultUrl.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl));
+                communityArticleImagesMapper.updateById(image);
+
+                //删除临时的原文件
+                org.apache.commons.io.FileUtils.deleteQuietly(new File(tempUrl));
+            }
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 处理图片:下载、压缩、上传到OSS
+     */
+    private String processImage(String imageUrl, CommunityArticleImages image) throws Exception {
+        // 下载图片到临时文件
+        String tempUrl = System.getProperty("java.io.tmpdir") + File.separator + "original_" + image.getImageUrl().substring(image.getImageUrl().lastIndexOf("/") + 1);
+        File tempFile = new File(tempUrl);
+        URL url = new URL(imageUrl);
+        try (InputStream inputStream = url.openStream();
+             OutputStream outputStream = new FileOutputStream(tempFile)) {
+            IOUtils.copy(inputStream, outputStream);
+        }
+
+        // 4. 将图片进行压缩
+        String compressedFile = System.getProperty("java.io.tmpdir") + File.separator + "compress_" + image.getImageUrl().substring(image.getImageUrl().lastIndexOf("/") + 1);
+        ImageUtils.compressAndGenerateThumbnail(tempFile.getAbsolutePath(), compressedFile, 500, 350, 0.8f);
+
+        // 5. 将压缩后的图片上传到OSS
+        String compressedFileUrl = OssUtils.uploadFile(compressedFile);
+
+        // 6. 更新数据库
+        image.setCompressUrl(compressedFileUrl.replace("https://cysd.oss-cn-shanghai.aliyuncs.com", fileUrl));
+        communityArticleImagesMapper.updateById(image);
+
+        // 删除临时文件
+        org.apache.commons.io.FileUtils.deleteQuietly(new File(compressedFile));  // 删除压缩后的临时文件
+
+        return tempUrl;
+    }
+
+
+    /**
+     * 对URL中的中文字符进行编码,同时避免对协议部分(http:// 或 https://)和主机部分编码
+     */
+    private String encodeUrl(String url) throws UnsupportedEncodingException {
+        // 检查协议部分并分离
+        String protocol = "";
+        if (url.startsWith("http://")) {
+            protocol = "http://";
+            url = url.substring(7);
+        } else if (url.startsWith("https://")) {
+            protocol = "https://";
+            url = url.substring(8);
+        }
+
+        // 分离主机和端口部分
+        int pathStartIndex = url.indexOf("/");
+        String hostPart = url;
+        String pathPart = "";
+        if (pathStartIndex > -1) {
+            hostPart = url.substring(0, pathStartIndex); // 主机部分(包括端口号)
+            pathPart = url.substring(pathStartIndex);   // 路径部分
+        }
+
+        // 确保端口号部分不被错误编码,只有路径部分需要编码
+        String encodedPath = URLEncoder.encode(pathPart, "UTF-8");
+        // 保留斜杠和特定字符不被编码
+        encodedPath = encodedPath.replace("%2F", "/"); // 保留斜杠
+        // 确保空格被编码为 %20,而不是 +
+        encodedPath = encodedPath.replace("+", "%20");
+        encodedPath = encodedPath.replace("%28", "(").replace("%29", ")"); // 保留括号
+        encodedPath = encodedPath.replace("%2B", "+"); // 保留加号
+        // 返回完整的 URL
+        return protocol + hostPart + encodedPath;
+    }
+
     /**
      * 通用上传请求(多个)
      */

+ 6 - 0
ruoyi-common/pom.xml

@@ -170,6 +170,12 @@
             <artifactId>spring-boot-starter-test</artifactId>
         </dependency>
 
+        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.16.1</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 24 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java

@@ -17,6 +17,7 @@ import org.springframework.web.multipart.commons.CommonsMultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
+import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -275,6 +276,29 @@ public class FileUtils {
         }
     }
 
+    /**
+     * 获取文件类型(图片、音频、视频等)
+     *
+     * @param fileUrl 文件的URL
+     * @return 文件类型
+     */
+    public static String getFileTypeFromUrl(String fileUrl) throws IOException {
+        URL url = new URL(fileUrl);
+        try (InputStream inputStream = url.openStream()) {
+            Tika tika = new Tika();
+            String mimeType = tika.detect(inputStream);
+            if (mimeType.startsWith("image/")) {
+                return "image";
+            } else if (mimeType.startsWith("audio/")) {
+                return "audio";
+            } else if (mimeType.startsWith("video/")) {
+                return "video";
+            } else {
+                return "other";
+            }
+        }
+    }
+
     /**
      * 截取视频的指定时间帧,生成图片文件
      *

+ 19 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java

@@ -3,6 +3,7 @@ package com.ruoyi.common.utils.file;
 import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.utils.StringUtils;
+import net.coobird.thumbnailator.Thumbnails;
 import org.apache.poi.util.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -177,4 +178,22 @@ public class ImageUtils {
         }
         return new Color(r / count, g / count, b / count);
     }
+
+    /**
+     * 生成缩略图并进行压缩
+     *
+     * @param originalImagePath 原始图片路径
+     * @param thumbImagePath    缩略图保存路径
+     * @param width             缩略图宽度
+     * @param height            缩略图高度
+     * @param quality           压缩质量,范围0-1,值越低压缩越厉害
+     * @throws IOException      IO异常
+     */
+    public static void compressAndGenerateThumbnail(String originalImagePath, String thumbImagePath, int width, int height, float quality) throws IOException {
+        // 压缩图片并生成缩略图
+        Thumbnails.of(new File(originalImagePath))
+                .size(width, height)  // 设置缩略图的宽高
+                .outputQuality(quality)  // 设置图片压缩质量
+                .toFile(new File(thumbImagePath));  // 输出文件
+    }
 }

+ 8 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/webSocket/WebSocketServer.java

@@ -233,10 +233,14 @@ public class WebSocketServer {
      * 实现服务器主动推送
      */
     private void sendMessage(String type, Object data) throws IOException {
-        Map<String, Object> result = new HashMap<>();
-        result.put("type", type);
-        result.put("data", data);
-        this.session.getAsyncRemote().sendText(JSON.toJSONString(result));
+        if (this.session.isOpen()) {
+            Map<String, Object> result = new HashMap<>();
+            result.put("type", type);
+            result.put("data", data);
+            this.session.getAsyncRemote().sendText(JSON.toJSONString(result));
+        } else {
+            LOGGER.warn("会话已关闭,无法发送消息。");
+        }
     }
 
 

+ 8 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/CommunityArticleController.java

@@ -1147,14 +1147,19 @@ public class CommunityArticleController extends BaseController {
     @ApiOperation("查询用户合集")
     @GetMapping("/getCollection")
     @Anonymous
-    public AjaxResult getCollection(Long collectionId, Long searchType) {
+    public AjaxResult getCollection(Long collectionId, Long searchType,@RequestParam(required = false) Long userId) {
         if (Objects.isNull(collectionId)) {
             return AjaxResult.error("合集不存在!");
         }
+
+        if (Objects.isNull(userId)) {
+            userId = SecurityUtils.getUserId();
+        }
+
         List<CommunityCollectionArticleVo> collectionArticleVos = null;
         JSONArray jsonArray;
         try {
-            jsonArray = communityCollectionService.selectArticleInfoInCollection(collectionId, searchType);
+            jsonArray = communityCollectionService.selectArticleInfoInCollection(userId,collectionId, searchType);
         } catch (Exception e) {
             System.out.println(e.getMessage());
             throw new ProjectException();
@@ -1232,6 +1237,7 @@ public class CommunityArticleController extends BaseController {
 
     @ApiOperation("个人喜欢文章")
     @GetMapping("/userLike")
+    @Anonymous
     public AjaxResult userLike(@RequestParam(required = false) Long userId) {
         int pageNum = Convert.toInt(ServletUtils.getParameter("pageNum"), 1);
         int pageSize = Convert.toInt(ServletUtils.getParameter("pageSize"), 10);

+ 6 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/Community/CommunityArticleImages.java

@@ -46,7 +46,12 @@ public class CommunityArticleImages implements Serializable {
     @TableField("image_url")
     private String imageUrl;
 
-
+    /**
+     * 缩略图图片
+     */
+    @ApiModelProperty("缩略图图片")
+    @TableField("compress_url")
+    private String compressUrl;
 
     /** 创建者 */
     private Long createBy;

+ 2 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/service/CommunityCollectionServiceImpl.java

@@ -85,7 +85,7 @@ public class CommunityCollectionServiceImpl extends ServiceImpl<CommunityCollect
      * @return 文章信息
      */
     @Override
-    public JSONArray selectArticleInfoInCollection(Long collectionId, Long searchType) {
+    public JSONArray selectArticleInfoInCollection(Long userId,Long collectionId, Long searchType) {
         if (searchType == null) {
             searchType = 1L;
         }
@@ -137,7 +137,7 @@ public class CommunityCollectionServiceImpl extends ServiceImpl<CommunityCollect
         //查询当前用户是否订阅
         CommunityCollectionUser communityCollectionUser = communityCollectionUserMapper.selectOne(new QueryWrapper<CommunityCollectionUser>()
                 .eq("collection_id", collectionId)
-                .eq("user_id", SecurityUtils.getUserId())
+                .eq("user_id", userId)
                 .and((wrapper) -> {
                     wrapper.ne("is_delete", true)
                             .or()

+ 1 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/service/ICommunityCollectionService.java

@@ -4,7 +4,6 @@ import com.alibaba.fastjson2.JSONArray;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.generator.domain.Community.CommunityCollection;
 import com.ruoyi.generator.domain.Community.CommunityCollectionArticle;
-import com.ruoyi.generator.vo.CommunityCollectionArticleVo;
 import com.ruoyi.generator.vo.CommunityCollectionVo;
 
 import java.util.List;
@@ -29,7 +28,7 @@ public interface ICommunityCollectionService extends IService<CommunityCollectio
      * @param collectionId 合集id
      * @return 文章信息
      */
-    JSONArray selectArticleInfoInCollection(Long collectionId,Long searchType);
+    JSONArray selectArticleInfoInCollection(Long userId,Long collectionId,Long searchType);
 
     /**
      * 删除合集

+ 0 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/vo/CommunityArticleVo.java

@@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.generator.domain.Community.CommunityArticleImages;
-import com.ruoyi.generator.domain.Community.CommunityCommentRaffle;
 import com.ruoyi.generator.domain.Community.CommunityTag;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 1 - 0
ruoyi-generator/src/main/resources/mapper/community/ArticleMapper.xml

@@ -125,6 +125,7 @@
         'id', IFNULL(b.id,''),
         'articleId', IFNULL(b.article_id,''),
         'imageUrl', IFNULL(b.image_url,''),
+        'compressUrl', IFNULL(b.compress_url,''),
         'createBy', IFNULL(b.create_by,''),
         'createTime', IFNULL(DATE_FORMAT(b.create_time,'%Y-%m-%d %H:%i:%s'),''),
         'updateBy', IFNULL(b.update_by,''),