mirror of
https://gitee.com/blossom-editor/blossom.git
synced 2025-12-08 01:38:27 +08:00
fix: 回收站文章导出与空内容文章导出
This commit is contained in:
parent
042ec82489
commit
03ee3978b8
@ -226,12 +226,11 @@ public class ArticleController {
|
|||||||
public void download(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
|
public void download(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
|
||||||
ArticleEntity article = baseService.selectById(id, false, true, false, AuthContext.getUserId());
|
ArticleEntity article = baseService.selectById(id, false, true, false, AuthContext.getUserId());
|
||||||
if (StrUtil.isBlank(article.getMarkdown())) {
|
if (StrUtil.isBlank(article.getMarkdown())) {
|
||||||
throw new IllegalArgumentException("文章内容为空,无法导出");
|
article.setMarkdown("文章无内容");
|
||||||
}
|
}
|
||||||
try (InputStream is = new ByteArrayInputStream(article.getMarkdown().getBytes(StandardCharsets.UTF_8));
|
try (InputStream is = new ByteArrayInputStream(article.getMarkdown().getBytes(StandardCharsets.UTF_8));
|
||||||
BufferedInputStream bis = new BufferedInputStream(is)) {
|
BufferedInputStream bis = new BufferedInputStream(is)) {
|
||||||
String filename = URLEncodeUtil.encode(article.getName() + ".md");
|
String filename = URLEncodeUtil.encode(article.getName() + ".md");
|
||||||
|
|
||||||
DownloadUtil.forceDownload(response, bis, filename);
|
DownloadUtil.forceDownload(response, bis, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,7 +246,7 @@ public class ArticleController {
|
|||||||
public void downloadHtml(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
|
public void downloadHtml(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
|
||||||
ArticleEntity article = baseService.selectById(id, false, false, true, AuthContext.getUserId());
|
ArticleEntity article = baseService.selectById(id, false, false, true, AuthContext.getUserId());
|
||||||
if (StrUtil.isBlank(article.getHtml())) {
|
if (StrUtil.isBlank(article.getHtml())) {
|
||||||
throw new IllegalArgumentException("文章内容为空,无法导出");
|
article.setHtml("<span>文章无内容</span>");
|
||||||
}
|
}
|
||||||
String reportHtml = ArticleUtil.toHtml(article, userService.selectById(AuthContext.getUserId()));
|
String reportHtml = ArticleUtil.toHtml(article, userService.selectById(AuthContext.getUserId()));
|
||||||
try (InputStream is = new ByteArrayInputStream(reportHtml.getBytes(StandardCharsets.UTF_8));
|
try (InputStream is = new ByteArrayInputStream(reportHtml.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|||||||
@ -1,15 +1,25 @@
|
|||||||
package com.blossom.backend.server.article.recycle;
|
package com.blossom.backend.server.article.recycle;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.net.URLEncodeUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.blossom.backend.base.auth.AuthContext;
|
import com.blossom.backend.base.auth.AuthContext;
|
||||||
|
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleEntity;
|
||||||
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleListRes;
|
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleListRes;
|
||||||
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleRestoreReq;
|
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleRestoreReq;
|
||||||
|
import com.blossom.backend.server.utils.DownloadUtil;
|
||||||
import com.blossom.common.base.pojo.R;
|
import com.blossom.common.base.pojo.R;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,4 +57,24 @@ public class ArticleRecycleController {
|
|||||||
baseService.restore(AuthContext.getUserId(), req.getId());
|
baseService.restore(AuthContext.getUserId(), req.getId());
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文章
|
||||||
|
*
|
||||||
|
* @param id 文章ID
|
||||||
|
* @param response 文章流
|
||||||
|
* @apiNote 返回流
|
||||||
|
*/
|
||||||
|
@GetMapping("/download")
|
||||||
|
public void download(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
|
||||||
|
ArticleRecycleEntity article = baseService.selectById(id);
|
||||||
|
if (StrUtil.isBlank(article.getMarkdown())) {
|
||||||
|
article.setMarkdown("文章无内容");
|
||||||
|
}
|
||||||
|
try (InputStream is = new ByteArrayInputStream(article.getMarkdown().getBytes(StandardCharsets.UTF_8));
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(is)) {
|
||||||
|
String filename = URLEncodeUtil.encode(article.getName() + ".md");
|
||||||
|
DownloadUtil.forceDownload(response, bis, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,15 @@ public class ArticleRecycleService extends ServiceImpl<ArticleRecycleMapper, Art
|
|||||||
return baseMapper.listAll(userId);
|
return baseMapper.listAll(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询
|
||||||
|
*
|
||||||
|
* @param id 文章ID
|
||||||
|
*/
|
||||||
|
public ArticleRecycleEntity selectById(Long id) {
|
||||||
|
return baseMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 还原数据
|
* 还原数据
|
||||||
*
|
*
|
||||||
|
|||||||
@ -473,6 +473,11 @@ export const articleRecycleRestoreApi = (data?: object): Promise<any> => {
|
|||||||
return rq.post('/article/recycle/restore', data)
|
return rq.post('/article/recycle/restore', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const articleRecycleDownloadApi = (params?: object): Promise<any> => {
|
||||||
|
let config = { params: params, responseType: 'blob' }
|
||||||
|
return rq.get('/article/recycle/download', config)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文章全文搜索
|
* 文章全文搜索
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<div class="name">{{ recycle.name }}</div>
|
<div class="name">{{ recycle.name }}</div>
|
||||||
<div class="size">{{ recycle.delTime }}|{{ remainingDays(recycle.delTime) }}天后删除</div>
|
<div class="size">{{ recycle.delTime }}|{{ remainingDays(recycle.delTime) }}天后删除</div>
|
||||||
<el-button class="restore-btn" @click="restore(recycle.id)"><span class="iconbl bl-a-cloudupload-line"></span></el-button>
|
<el-button class="restore-btn" @click="restore(recycle.id)"><span class="iconbl bl-a-cloudupload-line"></span></el-button>
|
||||||
<el-button class="download-btn" @click=""><span class="iconbl bl-folder-download-line"></span></el-button>
|
<el-button class="download-btn" @click="download(recycle.id)"><span class="iconbl bl-folder-download-line"></span></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useUserStore } from '@renderer/stores/user'
|
import { useUserStore } from '@renderer/stores/user'
|
||||||
import { articleRecycleListApi, articleRecycleRestoreApi } from '@renderer/api/blossom'
|
import { articleRecycleListApi, articleRecycleRestoreApi, articleRecycleDownloadApi } from '@renderer/api/blossom'
|
||||||
import { isNull } from '@renderer/assets/utils/obj'
|
import { isNull } from '@renderer/assets/utils/obj'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
@ -68,6 +68,26 @@ const restore = (id: string) => {
|
|||||||
getBackupList()
|
getBackupList()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const download = (id: string) => {
|
||||||
|
articleRecycleDownloadApi({ id: id }).then((resp) => {
|
||||||
|
let filename: string = resp.headers.get('content-disposition')
|
||||||
|
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
|
||||||
|
let matches = filenameRegex.exec(filename)
|
||||||
|
if (matches != null && matches[1]) {
|
||||||
|
filename = decodeURI(matches[1].replace(/['"]/g, ''))
|
||||||
|
}
|
||||||
|
filename = decodeURI(filename)
|
||||||
|
let a = document.createElement('a')
|
||||||
|
let blob = new Blob([resp.data], { type: 'text/plain' })
|
||||||
|
let objectUrl = URL.createObjectURL(blob)
|
||||||
|
a.setAttribute('href', objectUrl)
|
||||||
|
a.setAttribute('download', filename)
|
||||||
|
a.click()
|
||||||
|
URL.revokeObjectURL(a.href)
|
||||||
|
a.remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user