🎨 Add API /api/export/exportResources
to export files and folders (#8841)
This commit is contained in:
parent
9ee922794e
commit
0c7e16e558
5 changed files with 162 additions and 0 deletions
40
API.md
40
API.md
|
@ -47,6 +47,7 @@
|
|||
* [List files](#List-files)
|
||||
* [Export](#Export)
|
||||
* [Export Markdown](#Export-Markdown)
|
||||
* [Export Files and Folders](#Export-files-and-folders)
|
||||
* [Conversion](#Conversion)
|
||||
* [Pandoc](#Pandoc)
|
||||
* [Notification](#Notification)
|
||||
|
@ -1118,6 +1119,45 @@ View API token in <kbd>Settings - About</kbd>, request header: `Authorization: T
|
|||
* `hPath`: human-readable path
|
||||
* `content`: Markdown content
|
||||
|
||||
### Export files and folders
|
||||
|
||||
* `/api/export/exportResources`
|
||||
* Parameters
|
||||
|
||||
```json
|
||||
{
|
||||
"paths": [
|
||||
"/conf/appearance/boot",
|
||||
"/conf/appearance/langs",
|
||||
"/conf/appearance/emojis/conf.json",
|
||||
"/conf/appearance/icons/index.html",
|
||||
],
|
||||
"name": "zip-file-name"
|
||||
}
|
||||
```
|
||||
|
||||
* `paths`: A list of file or folder paths to be exported, the same filename/folder name will be overwritten
|
||||
* `name`: (Optional) The exported file name, which defaults to `export-YYYY-MM-DD_hh-mm-ss.zip` when not set
|
||||
* Return value
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "",
|
||||
"data": {
|
||||
"path": "temp/export/zip-file-name.zip"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `path`: The path of `*.zip` file created
|
||||
* The directory structure in `zip-file-name.zip` is as follows:
|
||||
* `zip-file-name`
|
||||
* `boot`
|
||||
* `langs`
|
||||
* `conf.json`
|
||||
* `index.html`
|
||||
|
||||
## Conversion
|
||||
|
||||
### Pandoc
|
||||
|
|
40
API_zh_CN.md
40
API_zh_CN.md
|
@ -47,6 +47,7 @@
|
|||
* [列出文件](#列出文件)
|
||||
* [导出](#导出)
|
||||
* [导出 Markdown 文本](#导出-markdown-文本)
|
||||
* [导出文件与目录](#导出文件与目录)
|
||||
* [转换](#转换)
|
||||
* [Pandoc](#Pandoc)
|
||||
* [通知](#通知)
|
||||
|
@ -1110,6 +1111,45 @@
|
|||
* `hPath`:人类可读的路径
|
||||
* `content`:Markdown 内容
|
||||
|
||||
### 导出文件与目录
|
||||
|
||||
* `/api/export/exportResources`
|
||||
* 参数
|
||||
|
||||
```json
|
||||
{
|
||||
"paths": [
|
||||
"/conf/appearance/boot",
|
||||
"/conf/appearance/langs",
|
||||
"/conf/appearance/emojis/conf.json",
|
||||
"/conf/appearance/icons/index.html",
|
||||
],
|
||||
"name": "zip-file-name"
|
||||
}
|
||||
```
|
||||
|
||||
* `paths`:要导出的文件或文件夹路径列表,相同名称的文件/文件夹会被覆盖
|
||||
* `name`:(可选)导出的文件名,未设置时默认为 `export-YYYY-MM-DD_hh-mm-ss.zip`
|
||||
* 返回值
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "",
|
||||
"data": {
|
||||
"path": "temp/export/zip-file-name.zip"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `path`:创建的 `*.zip` 文件路径
|
||||
* `zip-file-name.zip` 中的目录结构如下所示:
|
||||
* `zip-file-name`
|
||||
* `boot`
|
||||
* `langs`
|
||||
* `conf.json`
|
||||
* `index.html`
|
||||
|
||||
## 转换
|
||||
|
||||
### Pandoc
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -240,6 +241,42 @@ func exportData(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func exportResources(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var name string
|
||||
if nil != arg["name"] {
|
||||
name = util.TruncateLenFileName(arg["name"].(string))
|
||||
}
|
||||
if name == "" {
|
||||
name = time.Now().Format("export-2006-01-02_15-04-05") // 生成的 *.zip 文件主文件名
|
||||
}
|
||||
|
||||
var resourcePaths []string // 文件/文件夹在工作空间中的路径
|
||||
if nil != arg["paths"] {
|
||||
for _, resourcePath := range arg["paths"].([]interface{}) {
|
||||
resourcePaths = append(resourcePaths, resourcePath.(string))
|
||||
}
|
||||
}
|
||||
|
||||
zipFilePath, err := model.ExportResources(resourcePaths, name)
|
||||
if nil != err {
|
||||
ret.Code = 1
|
||||
ret.Msg = err.Error()
|
||||
ret.Data = map[string]interface{}{"closeTimeout": 7000}
|
||||
return
|
||||
}
|
||||
ret.Data = map[string]interface{}{
|
||||
"path": zipFilePath, // 相对于工作空间目录的路径
|
||||
}
|
||||
}
|
||||
|
||||
func batchExportMd(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
|
|
@ -246,6 +246,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||
ginServer.Handle("POST", "/api/export/exportDocx", model.CheckAuth, exportDocx)
|
||||
ginServer.Handle("POST", "/api/export/processPDF", model.CheckAuth, processPDF)
|
||||
ginServer.Handle("POST", "/api/export/preview", model.CheckAuth, exportPreview)
|
||||
ginServer.Handle("POST", "/api/export/exportResources", model.CheckAuth, exportResources)
|
||||
ginServer.Handle("POST", "/api/export/exportAsFile", model.CheckAuth, exportAsFile)
|
||||
ginServer.Handle("POST", "/api/export/exportData", model.CheckAuth, exportData)
|
||||
ginServer.Handle("POST", "/api/export/exportDataInFolder", model.CheckAuth, exportDataInFolder)
|
||||
|
|
|
@ -324,6 +324,50 @@ func exportData(exportFolder string) (zipPath string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func ExportResources(resourcePaths []string, mainName string) (exportFilePath string, err error) {
|
||||
WaitForWritingFiles()
|
||||
|
||||
// 用于导出的临时文件夹完整路径
|
||||
exportFolderPath := filepath.Join(util.TempDir, "export", mainName)
|
||||
if err = os.MkdirAll(exportFolderPath, 0755); nil != err {
|
||||
logging.LogErrorf("create export temp folder failed: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将需要导出的文件/文件夹复制到临时文件夹
|
||||
for _, resourcePath := range resourcePaths {
|
||||
resourceFullPath := filepath.Join(util.WorkspaceDir, resourcePath) // 资源完整路径
|
||||
resourceBaseName := filepath.Base(resourceFullPath) // 资源名称
|
||||
resourceCopyPath := filepath.Join(exportFolderPath, resourceBaseName) // 资源副本完整路径
|
||||
if err = filelock.Copy(resourceFullPath, resourceCopyPath); nil != err {
|
||||
logging.LogErrorf("copy resource will be exported from [%s] to [%s] failed: %s", resourcePath, resourceCopyPath, err)
|
||||
err = fmt.Errorf(Conf.Language(14), err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
zipFilePath := exportFolderPath + ".zip" // 导出的 *.zip 文件完整路径
|
||||
zip, err := gulu.Zip.Create(zipFilePath)
|
||||
if nil != err {
|
||||
logging.LogErrorf("create export zip [%s] failed: %s", zipFilePath, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = zip.AddDirectory(mainName, exportFolderPath); nil != err {
|
||||
logging.LogErrorf("create export zip [%s] failed: %s", exportFolderPath, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = zip.Close(); nil != err {
|
||||
logging.LogErrorf("close export zip failed: %s", err)
|
||||
}
|
||||
|
||||
os.RemoveAll(exportFolderPath)
|
||||
|
||||
exportFilePath = path.Join("temp", "export", mainName+".zip") // 导出的 *.zip 文件相对于工作区目录的路径
|
||||
return
|
||||
}
|
||||
|
||||
func Preview(id string) (retStdHTML string, retOutline []*Path) {
|
||||
tree, _ := loadTreeByBlockID(id)
|
||||
tree = exportTree(tree, false, false, false,
|
||||
|
|
Loading…
Add table
Reference in a new issue