Forráskód Böngészése

添加并实现文件上传功能

reghao 1 éve
szülő
commit
57e19fc293

+ 145 - 0
web/src/main/java/cn/reghao/bnt/web/blog/BlogController.java

@@ -0,0 +1,145 @@
+package cn.reghao.bnt.web.blog;
+
+import cn.reghao.bnt.web.sys.service.FileService;
+import cn.reghao.jutil.web.ServletUtil;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.ServletRequestUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author reghao
+ * @date 2024-07-24 13:50:19
+ */
+@Controller
+public class BlogController {
+    private final FileService fileService;
+
+    public BlogController(FileService fileService) {
+        this.fileService = fileService;
+    }
+
+    @GetMapping(value = {"/blog", "/blog/index"})
+    public String index(ModelMap model, HttpServletRequest request) {
+        // 调用 ContentsDirective
+        String order = ServletRequestUtils.getStringParameter(request, "order", "newest");
+        int pageNo = ServletRequestUtils.getIntParameter(request, "pageNo", 1);
+        //model.put("user", accountQuery.getUserCard());
+        model.put("order", order);
+        model.put("pageNo", pageNo);
+
+        setChannels(model);
+        return "/blog/index";
+    }
+
+    @GetMapping("/category")
+    public String category(ModelMap model) {
+        /*List<CategoryCount> list = categoryService.findCategoryCountByPage(CategoryType.Category.getValue(), 1, 100).getContent();
+        model.put("results", list);
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/category/{name}")
+    public String category1(@PathVariable("name") String name, ModelMap model) {
+        /*int pageNo = ServletRequestUtils.getIntParameter(ServletUtil.getRequest(), "pageNo", 1);
+        Page<UserArticle> page = articleQuery.findByPage1(10, pageNo, name, 1);
+        model.put("results", page);
+        model.put("name", name);
+        model.put("user", accountQuery.getUserCard());
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/tag")
+    public String tag(ModelMap model) {
+        /*List<CategoryCount> list = categoryService.findCategoryCountByPage(CategoryType.Tag.getValue(), 1, 100).getContent();
+        model.put("results", list);
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/tag/{name}")
+    public String tag1(@PathVariable String name, ModelMap model) {
+        /*int pageNo = ServletRequestUtils.getIntParameter(ServletUtil.getRequest(), "pageNo", 1);
+        Page<UserArticle> page = articleQuery.findByPage1(10, pageNo, name, 2);
+        model.put("results", page);
+        model.put("name", name);
+        model.put("user", accountQuery.getUserCard());
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/archive")
+    public String archive(ModelMap model) {
+        /*List<ArchiveArticle> results = articleQuery.getArchiveArticles();
+        model.put("user", accountQuery.getUserCard());
+        model.put("results", results);
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/post/{articleId}")
+    public String article(@PathVariable("articleId") String articleId, ModelMap model) {
+        /*ArticleVO articleVO = articleQuery.getArticle(articleId);
+        if (articleVO == null) {
+            model.put("title", "Not Found");
+            model.put("content", "文章不存在");
+            setChannels(model);
+            return "/classic/zzz/notfound";
+        }
+
+        articleViewService.incr(articleId);
+        model.put("user", accountQuery.getUserCard());
+        model.put("view", articleVO);
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/search")
+    public String search(String kw, ModelMap model) {
+        Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "createTime"));
+        /*Page<UserArticle> page = articleSearch.search(kw, pageable);
+
+        model.put("results", page);
+        model.put("kw", kw);
+        model.put("user", accountQuery.getUserCard());
+
+        setChannels(model);*/
+        return "/blog/index";
+    }
+
+    @GetMapping("/file/**")
+    @ResponseBody
+    public void getFile() throws IOException {
+        HttpServletRequest servletRequest = ServletUtil.getRequest();
+        String uri = servletRequest.getRequestURI();
+        String uri1 = URLDecoder.decode(uri, StandardCharsets.UTF_8);
+        String objectName =  uri1.replaceFirst("/", "");
+        fileService.getFile(objectName);
+    }
+
+    private void setChannels(ModelMap model) {
+        /*List<Channel> channels = new ArrayList<>();
+        channels.add(new Channel("分类", "category"));
+        channels.add(new Channel("标签", "tag"));
+        channels.add(new Channel("归档", "archive"));
+        model.put("searchBox", true);
+        model.put("channels", channels);*/
+    }
+}

+ 2 - 0
web/src/main/java/cn/reghao/bnt/web/config/AppProperties.java

@@ -18,4 +18,6 @@ public class AppProperties {
     private String cookiePath;
     private String cacheDir;
     private String baseDir;
+    private String storeDir;
+    private String indexDir;
 }

+ 38 - 17
web/src/main/java/cn/reghao/bnt/web/sys/controller/FileController.java

@@ -1,21 +1,19 @@
 package cn.reghao.bnt.web.sys.controller;
 
+import cn.reghao.bnt.web.sys.model.po.DiskFile;
 import cn.reghao.bnt.web.sys.service.FileService;
 import cn.reghao.jutil.jdk.result.WebResult;
 import cn.reghao.jutil.web.ServletUtil;
+import org.springframework.data.domain.Page;
 import org.springframework.http.MediaType;
 import org.springframework.stereotype.Controller;
-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.ResponseBody;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -23,7 +21,7 @@ import java.util.Map;
  * @date 2024-01-20 17:24:58
  */
 @Controller
-@RequestMapping
+@RequestMapping("/admin/file")
 public class FileController {
     private final FileService fileService;
 
@@ -31,9 +29,28 @@ public class FileController {
         this.fileService = fileService;
     }
 
-    @PostMapping(value = "/api/file/upload", produces = MediaType.APPLICATION_JSON_VALUE)
+    @GetMapping("/list")
+    public String list(ModelMap model, HttpServletRequest request) {
+        int pageNumber = Integer.parseInt(ServletUtil.getRequestParam("pageNo", "1"));
+        Page<DiskFile> page = fileService.getDiskFiles(pageNumber);
+        page.getContent().forEach(fileMeta -> {
+            String objectName = fileMeta.getObjectName();
+            fileMeta.setObjectName(String.format("/%s", objectName));
+        });
+
+        model.put("page", page);
+        return "/admin/file/imglist";
+    }
+
+    @GetMapping("/upload")
+    public String upload(ModelMap model, HttpServletRequest request) {
+        model.put("id", 1);
+        return "/admin/file/fileupload";
+    }
+
+    @PostMapping(value = "/upload/image", produces = MediaType.APPLICATION_JSON_VALUE)
     @ResponseBody
-    public String imageUpload(MultipartFile file) throws Exception {
+    public String uploadImage(MultipartFile file) throws Exception {
         String url = fileService.putFile(file);
         Map<String, String> map = new HashMap<>();
         map.put("name", file.getOriginalFilename());
@@ -41,13 +58,17 @@ public class FileController {
         return WebResult.success(map);
     }
 
-    @GetMapping("/file/**")
+    @PostMapping(value = "/upload/images", produces = MediaType.APPLICATION_JSON_VALUE)
     @ResponseBody
-    public void getFile() throws IOException {
-        HttpServletRequest servletRequest = ServletUtil.getRequest();
-        String uri = servletRequest.getRequestURI();
-        String uri1 = URLDecoder.decode(uri, StandardCharsets.UTF_8);
-        String objectName =  uri1.replaceFirst("/", "");
-        fileService.getFile(objectName);
+    public String uploadImages(@RequestParam("files") List<MultipartFile> files) {
+        files.forEach(file -> {
+            try {
+                fileService.putFile(file);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        });
+
+        return WebResult.success();
     }
 }

+ 162 - 4
web/src/main/java/cn/reghao/bnt/web/sys/service/FileService.java

@@ -1,15 +1,173 @@
 package cn.reghao.bnt.web.sys.service;
 
+import cn.reghao.bnt.web.config.AppProperties;
+import cn.reghao.bnt.web.sys.db.repository.DiskFileRepository;
+import cn.reghao.bnt.web.sys.model.po.DiskFile;
+import cn.reghao.jutil.jdk.security.DigestUtil;
+import cn.reghao.jutil.web.ServletUtil;
+import org.apache.commons.io.FileUtils;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletResponse;
 import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+import java.util.UUID;
 
 /**
  * @author reghao
  * @date 2024-01-19 21:29:24
  */
-public interface FileService {
-    void initLocalStore() throws IOException;
-    void getFile(String objectName) throws IOException;
-    String putFile(MultipartFile file) throws Exception;
+@Service
+public class FileService {
+    // 1MiB
+    private final int bufSize = 1024*1024;
+    private final AppProperties appProperties;
+    private final DiskFileRepository diskFileRepository;
+
+    public FileService(DiskFileRepository diskFileRepository, AppProperties appProperties) {
+        this.diskFileRepository = diskFileRepository;
+        this.appProperties = appProperties;
+    }
+
+    @PostConstruct
+    public void initLocalStore() throws IOException {
+        String storeDir = appProperties.getStoreDir();
+        File dir1 = new File(storeDir);
+        if (!dir1.exists()) {
+            FileUtils.forceMkdir(dir1);
+        }
+
+        String indexDir = appProperties.getIndexDir();
+        File dir2 = new File(indexDir);
+        if (!dir2.exists()) {
+            FileUtils.forceMkdir(dir2);
+        }
+    }
+
+    public void getFile(String objectName) throws IOException {
+        DiskFile diskFile = diskFileRepository.findByObjectName(objectName);
+        if (diskFile == null) {
+            writeResponse(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+
+        String absolutePath = diskFile.getAbsolutePath();
+        String contentType = diskFile.getContentType();
+        long size = diskFile.getSize();
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setStatus(HttpServletResponse.SC_OK);
+        response.setContentType(contentType);
+        response.setContentLengthLong(size);
+
+        OutputStream outputStream = response.getOutputStream();
+        writeResponse(outputStream, absolutePath, 0, size);
+    }
+
+    private void writeResponse(int statusCode) throws IOException {
+        HttpServletResponse response = ServletUtil.getResponse();
+        response.setStatus(statusCode);
+        OutputStream outputStream = response.getOutputStream();
+        outputStream.flush();
+        outputStream.close();
+    }
+
+    private void writeResponse(OutputStream outputStream, String absolutePath, long start, long end) throws IOException {
+        RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
+        raf.seek(start);
+
+        long len = end-start+1;
+        if (len < bufSize) {
+            int len1 = (int) len;
+            byte[] buf1 = new byte[len1];
+            int readLen1 = raf.read(buf1, 0, len1);
+            outputStream.write(buf1, 0, readLen1);
+        } else {
+            byte[] buf = new byte[bufSize];
+            long totalRead = 0;
+            int readLen;
+            while ((readLen = raf.read(buf, 0, bufSize)) != -1) {
+                outputStream.write(buf, 0, readLen);
+                totalRead += readLen;
+
+                long left = len - totalRead;
+                if (left < bufSize) {
+                    int left1 = (int) left;
+                    byte[] buf1 = new byte[left1];
+                    int readLen1 = raf.read(buf1, 0, left1);
+                    outputStream.write(buf1, 0, readLen1);
+                    break;
+                }
+            }
+        }
+
+        outputStream.flush();
+        outputStream.close();
+        raf.close();
+    }
+
+    public String putFile(MultipartFile file) throws Exception {
+        long size = file.getSize();
+        String filename = file.getOriginalFilename();
+        String suffix = getSuffix(filename);
+
+        String objectId = UUID.randomUUID().toString().replace("-", "");;
+        String objectName;
+        if (suffix.isBlank()) {
+            objectName = String.format("file/%s", objectId);
+        } else {
+            objectName = String.format("file/%s%s", objectId, suffix);
+        }
+
+        String contentId = UUID.randomUUID().toString().replace("-", "");
+        File savedFile = saveFile(file.getInputStream(), contentId, suffix);
+        String contentType = Files.probeContentType(Path.of(savedFile.getAbsolutePath()));
+        String sha256sum = DigestUtil.sha256sum(savedFile.getAbsolutePath());
+
+        List<DiskFile> diskFiles = diskFileRepository.findBySha256sum(sha256sum);
+        DiskFile diskFile;
+        if (!diskFiles.isEmpty()) {
+            DiskFile existFile = diskFiles.get(0);
+            diskFile = new DiskFile(objectName, objectId, existFile, filename);
+            FileUtils.deleteQuietly(savedFile);
+        } else {
+            diskFile = new DiskFile(objectName, objectId, savedFile.getAbsolutePath(), sha256sum, filename, contentType, size);
+        }
+
+        diskFileRepository.save(diskFile);
+        return "/" + objectName;
+    }
+
+    private File saveFile(InputStream inputStream, String contentId, String suffix) throws IOException {
+        String absolutePath = String.format("%s/%s%s", appProperties.getStoreDir(), contentId, suffix);
+        File file = new File(absolutePath);
+        if (file.exists()) {
+            throw new IOException(absolutePath + " exist");
+        }
+
+        Files.copy(inputStream, Path.of(absolutePath), StandardCopyOption.REPLACE_EXISTING);
+        return file;
+    }
+
+    private String getSuffix(String filename) {
+        if (filename == null) {
+            return "";
+        }
+
+        int idx = filename.lastIndexOf(".");
+        return idx == -1 ? "" : filename.substring(idx);
+    }
+
+    public Page<DiskFile> getDiskFiles(int pageNumber) {
+        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
+        PageRequest pageRequest = PageRequest.of(pageNumber-1, 12, sort);
+        return diskFileRepository.findAll(pageRequest);
+    }
 }

+ 0 - 156
web/src/main/java/cn/reghao/bnt/web/sys/service/FileServiceImpl.java

@@ -1,156 +0,0 @@
-package cn.reghao.bnt.web.sys.service;
-
-import cn.reghao.bnt.web.sys.db.repository.DiskFileRepository;
-import cn.reghao.bnt.web.sys.model.po.DiskFile;
-import cn.reghao.jutil.jdk.security.DigestUtil;
-import cn.reghao.jutil.web.ServletUtil;
-import org.apache.commons.io.FileUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * @author reghao
- * @date 2024-01-19 21:29:24
- */
-@Service
-public class FileServiceImpl implements FileService {
-    // 1MiB
-    private final int bufSize = 1024*1024;
-    private final String storeDir = "";
-    private final DiskFileRepository diskFileRepository;
-
-    public FileServiceImpl(DiskFileRepository diskFileRepository) {
-        this.diskFileRepository = diskFileRepository;
-    }
-
-    @Override
-    public void initLocalStore() throws IOException {
-        File dir1 = new File(storeDir);
-        if (!dir1.exists()) {
-            //FileUtils.forceMkdir(dir1);
-        }
-    }
-
-    @Override
-    public void getFile(String objectName) throws IOException {
-        DiskFile diskFile = diskFileRepository.findByObjectName(objectName);
-        if (diskFile == null) {
-            writeResponse(HttpServletResponse.SC_NOT_FOUND);
-            return;
-        }
-
-        String absolutePath = diskFile.getAbsolutePath();
-        String contentType = diskFile.getContentType();
-        long size = diskFile.getSize();
-        HttpServletResponse response = ServletUtil.getResponse();
-        response.setStatus(HttpServletResponse.SC_OK);
-        response.setContentType(contentType);
-        response.setContentLengthLong(size);
-
-        OutputStream outputStream = response.getOutputStream();
-        writeResponse(outputStream, absolutePath, 0, size);
-    }
-
-    private void writeResponse(int statusCode) throws IOException {
-        HttpServletResponse response = ServletUtil.getResponse();
-        response.setStatus(statusCode);
-        OutputStream outputStream = response.getOutputStream();
-        outputStream.flush();
-        outputStream.close();
-    }
-
-    private void writeResponse(OutputStream outputStream, String absolutePath, long start, long end) throws IOException {
-        RandomAccessFile raf = new RandomAccessFile(absolutePath, "r");
-        raf.seek(start);
-
-        long len = end-start+1;
-        if (len < bufSize) {
-            int len1 = (int) len;
-            byte[] buf1 = new byte[len1];
-            int readLen1 = raf.read(buf1, 0, len1);
-            outputStream.write(buf1, 0, readLen1);
-        } else {
-            byte[] buf = new byte[bufSize];
-            long totalRead = 0;
-            int readLen;
-            while ((readLen = raf.read(buf, 0, bufSize)) != -1) {
-                outputStream.write(buf, 0, readLen);
-                totalRead += readLen;
-
-                long left = len - totalRead;
-                if (left < bufSize) {
-                    int left1 = (int) left;
-                    byte[] buf1 = new byte[left1];
-                    int readLen1 = raf.read(buf1, 0, left1);
-                    outputStream.write(buf1, 0, readLen1);
-                    break;
-                }
-            }
-        }
-
-        outputStream.flush();
-        outputStream.close();
-        raf.close();
-    }
-
-    @Override
-    public String putFile(MultipartFile file) throws Exception {
-        long size = file.getSize();
-        String filename = file.getOriginalFilename();
-        String suffix = getSuffix(filename);
-
-        String objectId = UUID.randomUUID().toString().replace("-", "");;
-        String objectName;
-        if (suffix.isBlank()) {
-            objectName = String.format("file/%s", objectId);
-        } else {
-            objectName = String.format("file/%s%s", objectId, suffix);
-        }
-
-        String contentId = UUID.randomUUID().toString().replace("-", "");
-        File savedFile = saveFile(file.getInputStream(), contentId, suffix);
-        String contentType = Files.probeContentType(Path.of(savedFile.getAbsolutePath()));
-        String sha256sum = DigestUtil.sha256sum(savedFile.getAbsolutePath());
-
-        List<DiskFile> diskFiles = diskFileRepository.findBySha256sum(sha256sum);
-        DiskFile diskFile;
-        if (!diskFiles.isEmpty()) {
-            DiskFile existFile = diskFiles.get(0);
-            diskFile = new DiskFile(objectName, objectId, existFile, filename);
-            FileUtils.deleteQuietly(savedFile);
-        } else {
-            diskFile = new DiskFile(objectName, objectId, savedFile.getAbsolutePath(), sha256sum, filename, contentType, size);
-        }
-
-        diskFileRepository.save(diskFile);
-        return "/" + objectName;
-    }
-
-    private File saveFile(InputStream inputStream, String contentId, String suffix) throws IOException {
-        String absolutePath = String.format("%s/%s%s", storeDir, contentId, suffix);
-        File file = new File(absolutePath);
-        if (file.exists()) {
-            throw new IOException(absolutePath + " exist");
-        }
-
-        Files.copy(inputStream, Path.of(absolutePath), StandardCopyOption.REPLACE_EXISTING);
-        return file;
-    }
-
-    private String getSuffix(String filename) {
-        if (filename == null) {
-            return "";
-        }
-
-        int idx = filename.lastIndexOf(".");
-        return idx == -1 ? "" : filename.substring(idx);
-    }
-}

+ 2 - 0
web/src/main/resources/application.yml

@@ -59,3 +59,5 @@ app:
   cookiePath: /home/reghao/Downloads/cookie.txt
   cacheDir: /home/reghao/mnt
   baseDir: /opt/data/bntdata
+  storeDir: ${app.basedir}/file
+  indexDir: ${app.basedir}/index

+ 41 - 0
web/src/main/resources/templates/blog/index.html

@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body class="timo-layout-page">
+<div class="layui-card">
+    <div class="layui-card-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 数据统计</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th data-field="userId">site</th>
+                    <th data-field="screenName">parser</th>
+                    <th data-field="gender">URL 总量</th>
+                    <th data-field="signature">已爬取 URL</th>
+                    <th data-field="following">待爬取 URL</th>
+                    <th data-field="follower">粉丝</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td th:text="${item.userId}"></td>
+                    <td th:text="${item.screenName}"></td>
+                    <td th:text="${item.gender}"></td>
+                    <td th:text="${item.signature}"></td>
+                    <td th:text="${item.following}"></td>
+                    <td th:text="${item.follower}"></td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 1 - 1
web/src/main/resources/templates/console/object/upload.html

@@ -37,7 +37,7 @@
                         <label class="layui-form-label">上传文件</label>
                         <div class="layui-input-inline">
                             <button type="button" class="layui-btn upload-file" name="files[]"
-                                    th:attr="up-url=@{/store/object/upload}" up-field="path">
+                                    th:attr="up-url=@{/admin/file/upload/image}" up-field="path">
                                 <i class="layui-icon">&#xe67c;</i>上传图片
                             </button>
                         </div>