fix: 回收站文章导出与空内容文章导出

This commit is contained in:
xiaozzzi 2024-01-20 22:43:18 +08:00
parent 042ec82489
commit 03ee3978b8
5 changed files with 68 additions and 5 deletions

View File

@ -226,12 +226,11 @@ public class ArticleController {
public void download(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
ArticleEntity article = baseService.selectById(id, false, true, false, AuthContext.getUserId());
if (StrUtil.isBlank(article.getMarkdown())) {
throw new IllegalArgumentException("文章内容为空,无法导出");
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);
}
}
@ -247,7 +246,7 @@ public class ArticleController {
public void downloadHtml(@RequestParam("id") Long id, HttpServletResponse response) throws IOException {
ArticleEntity article = baseService.selectById(id, false, false, true, AuthContext.getUserId());
if (StrUtil.isBlank(article.getHtml())) {
throw new IllegalArgumentException("文章内容为空,无法导出");
article.setHtml("<span>文章无内容</span>");
}
String reportHtml = ArticleUtil.toHtml(article, userService.selectById(AuthContext.getUserId()));
try (InputStream is = new ByteArrayInputStream(reportHtml.getBytes(StandardCharsets.UTF_8));

View File

@ -1,15 +1,25 @@
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.server.article.recycle.pojo.ArticleRecycleEntity;
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleListRes;
import com.blossom.backend.server.article.recycle.pojo.ArticleRecycleRestoreReq;
import com.blossom.backend.server.utils.DownloadUtil;
import com.blossom.common.base.pojo.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
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;
/**
@ -47,4 +57,24 @@ public class ArticleRecycleController {
baseService.restore(AuthContext.getUserId(), req.getId());
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);
}
}
}

View File

@ -47,6 +47,15 @@ public class ArticleRecycleService extends ServiceImpl<ArticleRecycleMapper, Art
return baseMapper.listAll(userId);
}
/**
* 根据ID查询
*
* @param id 文章ID
*/
public ArticleRecycleEntity selectById(Long id) {
return baseMapper.selectById(id);
}
/**
* 还原数据
*

View File

@ -473,6 +473,11 @@ export const articleRecycleRestoreApi = (data?: object): Promise<any> => {
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)
}
/**
*
*/

View File

@ -19,7 +19,7 @@
<div class="name">{{ recycle.name }}</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="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>
@ -29,7 +29,7 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
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 { isEmpty } from 'lodash'
import dayjs from 'dayjs'
@ -68,6 +68,26 @@ const restore = (id: string) => {
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>
<style scoped lang="scss">