diff --git a/client/src/pages/book/Bookshelf.tsx b/client/src/pages/book/Bookshelf.tsx index a39947b..f5407a7 100644 --- a/client/src/pages/book/Bookshelf.tsx +++ b/client/src/pages/book/Bookshelf.tsx @@ -159,6 +159,14 @@ function Bookshelf() { actionType: 'dialog', dialog: detailDialog(), }, + { + type: 'action', + label: '导出', + level: 'link', + size: 'sm', + actionType: 'download', + api: `${commonInfo.baseUrl}/book/export/\${id}`, + }, { className: 'text-danger btn-deleted', type: 'action', diff --git a/src/main/java/com/lanyuanxiaoyao/bookstore/controller/BookController.java b/src/main/java/com/lanyuanxiaoyao/bookstore/controller/BookController.java index 523fe47..374cd00 100644 --- a/src/main/java/com/lanyuanxiaoyao/bookstore/controller/BookController.java +++ b/src/main/java/com/lanyuanxiaoyao/bookstore/controller/BookController.java @@ -1,15 +1,25 @@ package com.lanyuanxiaoyao.bookstore.controller; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; import com.lanyuanxiaoyao.bookstore.entity.Book; +import com.lanyuanxiaoyao.bookstore.entity.Chapter; +import com.lanyuanxiaoyao.bookstore.entity.Line; import com.lanyuanxiaoyao.bookstore.entity.vo.Option; import com.lanyuanxiaoyao.bookstore.service.BookService; import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport; +import jakarta.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.time.LocalDateTime; +import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.function.Function; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -29,6 +39,39 @@ public class BookController extends SimpleControllerSupport { + result.append(StrUtil.format("第{}章 {}", chapter.getSequence(), chapter.getName())); + result.append("\n\n"); + chapter.getContent() + .stream() + .sorted(Comparator.comparing(Line::getSequence)) + .forEach(line -> { + result.append(line.getText()); + result.append("\n"); + }); + result.append("\n\n"); + }); + response.setHeader("Access-Control-Expose-Headers", "Content-Type"); + response.setHeader("Content-Type", "text/plain"); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", StrUtil.format("attachment; filename={}", URLUtil.encodeAll(StrUtil.format("{}.txt", book.getName())))); + IoUtil.copy(new ByteArrayInputStream(result.toString().getBytes()), response.getOutputStream()); + } + @Override protected Function saveItemMapper() { return item -> {