浏览代码

add:使用nginx和vsftp搭建图片服务器并使用Java上传图片到该图片服务器V1

lvzhiqiang 2 年之前
父节点
当前提交
d850d0af10

+ 7 - 0
pom.xml

@@ -147,6 +147,13 @@
             <artifactId>commonmark-ext-gfm-tables</artifactId>
             <version>0.21.0</version>
         </dependency>
+
+        <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
+        <dependency>
+            <groupId>commons-net</groupId>
+            <artifactId>commons-net</artifactId>
+            <version>3.10.0</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 6 - 4
src/main/java/top/lvzhiqiang/config/InitRunner.java

@@ -11,12 +11,11 @@ import top.lvzhiqiang.mapper.CoinMapper;
 import top.lvzhiqiang.mapper.DicCodeMapper;
 import top.lvzhiqiang.service.CoinService;
 import top.lvzhiqiang.service.Crawler4JavdbService;
+import top.lvzhiqiang.util.FtpUtil;
 
 import javax.annotation.Resource;
 import java.net.InetSocketAddress;
 import java.net.Proxy;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
@@ -30,8 +29,6 @@ import java.util.stream.Collectors;
 @Order(value = 1)
 public class InitRunner implements ApplicationRunner {
 
-    public static List<DicCode> dicCodeList = new ArrayList<>();
-
     @Resource
     private DicCodeMapper dicCodeMapper;
     @Resource
@@ -61,6 +58,11 @@ public class InitRunner implements ApplicationRunner {
             }
         }
 
+        Map<String, DicCode> dicCodeMap = dicCodeMapper.findAllMap();
+        FtpUtil.setParams(dicCodeMap.get("ftp_host").getCodeValue(), dicCodeMap.get("ftp_port").getCodeValue(),
+                dicCodeMap.get("ftp_username").getCodeValue(), dicCodeMap.get("ftp_password").getCodeValue(),
+                dicCodeMap.get("ftp_basepath").getCodeValue(), dicCodeMap.get("ftp_baseurl").getCodeValue());
+
         if (!"dev".equals(env)) {
             coinService.monitorJob();
             crawler4JavdbService.monitorActors();

+ 65 - 0
src/main/java/top/lvzhiqiang/controller/CoinController.java

@@ -2,14 +2,24 @@ package top.lvzhiqiang.controller;
 
 import com.alibaba.fastjson.JSONObject;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 import top.lvzhiqiang.dto.R;
 import top.lvzhiqiang.entity.CoinApiConfig;
+import top.lvzhiqiang.entity.FileImage;
 import top.lvzhiqiang.exception.ParameterException;
+import top.lvzhiqiang.mapper.CoinMapper;
 import top.lvzhiqiang.service.CoinApiConfigService;
 import top.lvzhiqiang.service.CoinService;
+import top.lvzhiqiang.util.DateUtils;
+import top.lvzhiqiang.util.FtpUtil;
 import top.lvzhiqiang.util.StringUtils;
 
 import javax.annotation.Resource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -27,6 +37,9 @@ public class CoinController {
     @Resource
     private CoinApiConfigService coinApiConfigService;
 
+    @Resource
+    private CoinMapper coinMapper;
+
     /**
      * 获取API配置信息
      *
@@ -96,4 +109,56 @@ public class CoinController {
 
         return R.ok().data(coinService.watchlistUpdate(symbol, remark));
     }
+
+    /**
+     * 上传图片
+     *
+     * @author lvzhiqiang
+     * 2023/12/29 10:26
+     */
+    @RequestMapping("/uploadImgs")
+    @ResponseBody
+    public R uploadImgs(@RequestParam("file") MultipartFile file, String remark) {
+        if (file == null) {
+            throw new ParameterException("文件为空!");
+        }
+
+        String imageUrl = "";
+        String imageSize = "";
+        try {
+            // 1、给上传的图片生成新的文件名
+            // 1.1获取原始文件名
+            String oldName = file.getOriginalFilename();
+            // 1.2使用FtpUtil工具类生成新的文件名,新文件名 = newName + 文件后缀
+            String newName = FtpUtil.genImageName();
+            newName = newName + oldName.substring(oldName.lastIndexOf("."));
+
+            // 2、把图片上传到图片服务器
+            // 2.1获取上传的io流
+            InputStream input = file.getInputStream();
+            // 2.2调用FtpUtil工具类进行上传
+            boolean result = FtpUtil.uploadFile(newName, input);
+            if (result) {
+                //返回给前端图片访问路径
+                imageUrl = FtpUtil.getBaseUrl() + LocalDate.now().format(DateUtils.dateFormatter_) + "/" + newName;
+                imageSize = BigDecimal.valueOf(file.getSize()).divide(new BigDecimal("1024")).setScale(0, RoundingMode.UP).toPlainString().concat("KB");
+
+                FileImage fileImage = new FileImage();
+                fileImage.setOldName(oldName);
+                fileImage.setNewName(newName);
+                fileImage.setSize(imageSize);
+                fileImage.setPath(imageUrl);
+                fileImage.setRemark(remark);
+                coinMapper.insertFileImage(fileImage);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        JSONObject result = new JSONObject();
+        result.put("imageUrl", imageUrl);
+        result.put("imageSize", imageSize);
+
+        return R.ok().data(result);
+    }
 }

+ 64 - 0
src/main/java/top/lvzhiqiang/entity/FileImage.java

@@ -0,0 +1,64 @@
+package top.lvzhiqiang.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 文件-图片表
+ *
+ * @author lvzhiqiang
+ * 2023/12/29 10:26
+ */
+@Data
+public class FileImage implements Serializable {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 老名称
+     */
+    private String oldName;
+
+    /**
+     * 新名称
+     */
+    private String newName;
+
+    /**
+     * 图片大小
+     */
+    private String size;
+
+    /**
+     * 图片路径
+     */
+    private String path;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 删除标志{1:正常,2:已删除}
+     */
+    private Integer deleteFlag;
+
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    /**
+     * 最后修改时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime modifyTime;
+}

+ 5 - 0
src/main/java/top/lvzhiqiang/mapper/CoinMapper.java

@@ -108,4 +108,9 @@ public interface CoinMapper {
 
     @Select("select * from coin_watchlist where symbol = #{symbol}")
     CoinWatchlist findWatchlistBySymbol(String symbol);
+
+
+    @Insert("INSERT INTO file_image(old_name, new_name, size, path, remark, create_time, modify_time) " +
+            "VALUES (#{oldName}, #{newName}, #{size}, #{path}, #{remark}, now(), now())")
+    int insertFileImage(FileImage fileImage);
 }

+ 6 - 0
src/main/java/top/lvzhiqiang/mapper/DicCodeMapper.java

@@ -2,10 +2,12 @@ package top.lvzhiqiang.mapper;
 
 import org.apache.ibatis.annotations.Delete;
 import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Select;
 import top.lvzhiqiang.entity.DicCode;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 字典码Mapper
@@ -41,6 +43,10 @@ public interface DicCodeMapper {
     @Select("SELECT * FROM dic_code WHERE delete_flag = 1")
     List<DicCode> findAll();
 
+    @Select("SELECT * FROM dic_code WHERE delete_flag = 1")
+    @MapKey("codeKey")
+    Map<String, DicCode> findAllMap();
+
     /**
      * 根据codeDesc模糊查询
      */

+ 2 - 0
src/main/java/top/lvzhiqiang/util/DateUtils.java

@@ -34,6 +34,7 @@ public class DateUtils {
      * (精确到天的)日期样式
      */
     public static final String PATTERN_TO_DAYS = "yyyy-MM-dd";
+    public static final String PATTERN_TO_DAYS_ = "yyyyMMdd";
     public static final String PATTERN_TO_DAYS2 = "yyyy.MM.dd";
 
     public static final String PATTERN_TO_DAYS3 = "yyyy年M月d日";
@@ -46,6 +47,7 @@ public class DateUtils {
     public static final String PATTERN_TO_MINUTES = "yyyy-M-d HH:mm";
 
     public static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(PATTERN_TO_DAYS);
+    public static final DateTimeFormatter dateFormatter_ = DateTimeFormatter.ofPattern(PATTERN_TO_DAYS_);
     public static final DateTimeFormatter dateFormatter2 = DateTimeFormatter.ofPattern(PATTERN_TO_DAYS2);
     public static final DateTimeFormatter dateFormatter3 = DateTimeFormatter.ofPattern(PATTERN_TO_DAYS3);
     public static final DateTimeFormatter dateFormatter4 = DateTimeFormatter.ofPattern(PATTERN_TO_DAYS4);

+ 127 - 0
src/main/java/top/lvzhiqiang/util/FtpUtil.java

@@ -0,0 +1,127 @@
+package top.lvzhiqiang.util;
+
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPReply;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.LocalDate;
+import java.util.Random;
+
+/**
+ * 用于上传文件的工具类
+ * https://juejin.cn/post/6894219004673294349<使用nginx和vsftp搭建图片服务器并使用Java上传图片到该图片服务器>
+ */
+public class FtpUtil {
+
+    private static String host;
+    private static int port;
+    private static String userName;
+    private static String passWord;
+    private static String basePath;
+    private static String baseUrl;
+
+    public static String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public static void setParams(String host_, String port_, String userName_, String passWord_, String basePath_, String baseUrl_) {
+        host = host_;
+        port = Integer.parseInt(port_);
+        userName = userName_;
+        passWord = passWord_;
+        basePath = basePath_;
+        baseUrl = baseUrl_;
+    }
+
+    public static boolean uploadFile(String filename, InputStream input) {
+        return uploadFile(host, port, userName, passWord, basePath, filename, input);
+    }
+
+    /**
+     * Description: 向FTP服务器上传文件
+     *
+     * @param host     FTP服务器ip
+     * @param port     FTP服务器端口
+     * @param username FTP登录账号
+     * @param password FTP登录密码
+     * @param basePath FTP服务器基础目录,/home/ftpuser/images
+     * @param filename 上传到FTP服务器上的文件名
+     * @param input    输入流
+     * @return 成功返回true,否则返回false
+     */
+    public static boolean uploadFile(String host, int port, String username, String password, String basePath, String filename, InputStream input) {
+        boolean result = false;
+        FTPClient ftpClient = new FTPClient();
+        try {
+            // 连接FTP服务器
+            //// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
+            ftpClient.connect(host, port);
+            // 登录
+            ftpClient.login(username, password);
+            int replyCode = ftpClient.getReplyCode();
+            if (!FTPReply.isPositiveCompletion(replyCode)) {
+                ftpClient.disconnect();
+                return result;
+            }
+
+            // 设置为被动模式
+            ftpClient.enterLocalPassiveMode();
+            // 设置编码格式为utf-8
+            ftpClient.setControlEncoding("UTF-8");
+            // 设置上传文件的类型为二进制类型
+            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
+            // 设置存储图片的文件夹
+            String workingDirectory = basePath.concat(LocalDate.now().format(DateUtils.dateFormatter_));
+            String[] split = workingDirectory.split("/");
+            for (String s : split) {
+                if (StringUtils.isEmpty(s)) {
+                    continue;
+                }
+                if (!ftpClient.changeWorkingDirectory(s)) {
+                    ftpClient.makeDirectory(s);
+                    ftpClient.changeWorkingDirectory(s);
+                }
+            }
+            // 上传文件
+            if (!ftpClient.storeFile(filename, input)) {
+                return result;
+            }
+
+            input.close();
+
+            result = true;
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (ftpClient.isConnected()) {
+                try {
+                    ftpClient.logout();
+                    ftpClient.disconnect();
+                } catch (IOException ioe) {
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 生成随机图片名
+     */
+    public static String genImageName() {
+        //取当前时间的长整形值包含毫秒
+        long millis = System.currentTimeMillis();
+        //加上三位随机数
+        Random random = new Random();
+        int end3 = random.nextInt(999);
+        //如果不足三位前面补0
+        String str = millis + String.format("%03d", end3);
+
+        return str;
+    }
+
+    public static void main(String[] args) {
+        System.out.println(genImageName());
+    }
+}

+ 4 - 0
src/main/resources/application.yml

@@ -1,4 +1,8 @@
 spring:
+  servlet:
+    multipart:
+      max-file-size: 10MB
+      max-request-size: 20MB
   application:
     name: jav
   # 指定运行环境

+ 13 - 0
src/main/resources/static/coin.html

@@ -279,6 +279,19 @@
             </tbody>
         </table>
     </div>
+    <hr/>
+    <div style="display: flex;">
+        <div style="margin-right:20px;">
+            <span class="font">uploadImgs</span>
+            <form method="post" action="coin/uploadImgs" enctype="multipart/form-data">
+                <span>备注</span>
+                <input type="text" name="remark" placeholder="可为空"/>
+                <span>file</span>
+                <input type="file" name="file" multiple/>
+                <input type="submit" value="提交">
+            </form>
+        </div>
+    </div>
 </div>
 
 <div id="watchlistpreview">