Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
solo-1
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
solo-1
Commits
da595c87
Unverified
Commit
da595c87
authored
May 21, 2020
by
Liang Ding
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
✨
新增 Markdown zip 导入方式 #128
parent
3e786b85
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
126 additions
and
54 deletions
+126
-54
src/main/java/org/b3log/solo/Server.java
src/main/java/org/b3log/solo/Server.java
+2
-1
src/main/java/org/b3log/solo/processor/console/AdminConsole.java
...n/java/org/b3log/solo/processor/console/AdminConsole.java
+50
-4
src/main/java/org/b3log/solo/service/ExportService.java
src/main/java/org/b3log/solo/service/ExportService.java
+4
-0
src/main/java/org/b3log/solo/service/ImportService.java
src/main/java/org/b3log/solo/service/ImportService.java
+57
-49
src/main/resources/admin/admin-others.ftl
src/main/resources/admin/admin-others.ftl
+9
-0
src/main/resources/lang_en_US.properties
src/main/resources/lang_en_US.properties
+2
-0
src/main/resources/lang_zh_CN.properties
src/main/resources/lang_zh_CN.properties
+2
-0
No files found.
src/main/java/org/b3log/solo/Server.java
View file @
da595c87
...
...
@@ -519,7 +519,8 @@ public final class Server extends BaseServer {
get
(
"/admin-preference.do"
,
adminConsole:
:
showAdminPreferenceFunction
).
get
(
"/console/export/sql"
,
adminConsole:
:
exportSQL
).
get
(
"/console/export/json"
,
adminConsole:
:
exportJSON
).
get
(
"/console/export/hexo"
,
adminConsole:
:
exportHexo
);
get
(
"/console/export/hexo"
,
adminConsole:
:
exportHexo
).
post
(
"/console/import/markdown-zip"
,
adminConsole:
:
importMarkdownZip
);
adminConsoleGroup
.
router
().
get
(
new
String
[]{
"/admin-article.do"
,
"/admin-article-list.do"
,
"/admin-comment-list.do"
,
...
...
src/main/java/org/b3log/solo/processor/console/AdminConsole.java
View file @
da595c87
...
...
@@ -12,6 +12,7 @@
package
org
.
b3log
.
solo
.
processor
.
console
;
import
jodd.io.ZipUtil
;
import
org.apache.commons.io.FileUtils
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang.time.DateFormatUtils
;
...
...
@@ -22,6 +23,8 @@ import org.b3log.latke.Keys;
import
org.b3log.latke.Latkes
;
import
org.b3log.latke.event.Event
;
import
org.b3log.latke.event.EventManager
;
import
org.b3log.latke.http.FileUpload
;
import
org.b3log.latke.http.Request
;
import
org.b3log.latke.http.RequestContext
;
import
org.b3log.latke.http.Response
;
import
org.b3log.latke.http.renderer.AbstractFreeMarkerRenderer
;
...
...
@@ -31,14 +34,12 @@ import org.b3log.latke.model.Plugin;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.plugin.ViewLoadEventData
;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.util.Strings
;
import
org.b3log.solo.Server
;
import
org.b3log.solo.model.Common
;
import
org.b3log.solo.model.Option
;
import
org.b3log.solo.model.UserExt
;
import
org.b3log.solo.service.DataModelService
;
import
org.b3log.solo.service.ExportService
;
import
org.b3log.solo.service.OptionQueryService
;
import
org.b3log.solo.service.UserQueryService
;
import
org.b3log.solo.service.*
;
import
org.b3log.solo.util.Markdowns
;
import
org.b3log.solo.util.Solos
;
import
org.json.JSONObject
;
...
...
@@ -101,6 +102,12 @@ public class AdminConsole {
@Inject
private
EventManager
eventManager
;
/**
* Import service.
*/
@Inject
private
ImportService
importService
;
/**
* Shows administrator index with the specified context.
*
...
...
@@ -220,6 +227,45 @@ public class AdminConsole {
fireFreeMarkerActionEvent
(
templateName
,
dataModel
);
}
/**
* Imports markdown zip.
*
* @param context the specified context
*/
public
void
importMarkdownZip
(
final
RequestContext
context
)
{
final
Request
request
=
context
.
getRequest
();
final
FileUpload
file
=
request
.
getFileUpload
(
"file"
);
final
String
[]
allowedSuffixArray
=
new
String
[]{
"zip"
};
final
String
fileName
=
file
.
getFilename
();
String
suffix
=
StringUtils
.
substringAfterLast
(
fileName
,
"."
);
if
(
StringUtils
.
isBlank
(
suffix
))
{
// TODO
return
;
}
if
(!
Strings
.
containsIgnoreCase
(
suffix
,
allowedSuffixArray
))
{
// TODO
return
;
}
try
{
final
byte
[]
bytes
=
file
.
getData
();
final
String
tmpDir
=
System
.
getProperty
(
"java.io.tmpdir"
);
final
String
date
=
DateFormatUtils
.
format
(
new
Date
(),
"yyyyMMddHHmmss"
);
final
String
zipPath
=
tmpDir
+
File
.
separator
+
"solo-import-"
+
date
+
".zip"
;
final
File
zipFile
=
new
File
(
zipPath
);
FileUtils
.
writeByteArrayToFile
(
zipFile
,
bytes
);
final
String
unzipPath
=
tmpDir
+
File
.
separator
+
"solo-import-"
+
date
;
final
File
unzipDir
=
new
File
(
unzipPath
);
ZipUtil
.
unzip
(
zipFile
,
unzipDir
);
importService
.
importMarkdownDir
(
unzipDir
);
FileUtils
.
deleteQuietly
(
zipFile
);
FileUtils
.
deleteQuietly
(
unzipDir
);
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
ERROR
,
"Imports markdown file failed"
,
e
);
return
;
}
}
/**
* Exports data as SQL zip file.
*
...
...
src/main/java/org/b3log/solo/service/ExportService.java
View file @
da595c87
...
...
@@ -260,6 +260,10 @@ public class ExportService {
*/
public
void
exportGitHub
()
{
try
{
if
(
Latkes
.
RuntimeMode
.
DEVELOPMENT
==
Latkes
.
getRuntimeMode
())
{
return
;
}
final
JSONObject
preference
=
optionQueryService
.
getPreference
();
if
(
null
==
preference
)
{
return
;
...
...
src/main/java/org/b3log/solo/service/ImportService.java
View file @
da595c87
...
...
@@ -35,7 +35,7 @@ import java.util.*;
* Import service.
*
* @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.1.
6, Apr 23
, 2020
* @version 1.0.1.
7, May 21
, 2020
* @since 2.2.0
*/
@Service
...
...
@@ -64,8 +64,7 @@ public class ImportService {
private
UserQueryService
userQueryService
;
/**
* Imports markdowns files as articles. See <a href="https://hacpai.com/article/1498490209748">Solo 支持 Hexo/Jekyll 数据导入</a> for
* more details.
* Imports markdown files as articles. See <a href="https://hacpai.com/article/1498490209748">Solo 支持 Hexo/Jekyll 数据导入</a> for more details.
*/
public
void
importMarkdowns
()
{
new
Thread
(()
->
{
...
...
@@ -80,65 +79,74 @@ public class ImportService {
}
final
File
markdownsPath
=
Latkes
.
getFile
(
"/markdowns"
);
LOGGER
.
debug
(
"Import directory ["
+
markdownsPath
.
getPath
()
+
"]"
);
importMarkdownDir
(
markdownsPath
);
}).
start
();
}
final
JSONObject
admin
=
userQueryService
.
getAdmin
();
if
(
null
==
admin
)
{
// Not init yet
return
;
}
/**
* Imports markdown files under the specified markdown files dir.
*
* @param markdownsDir the specified markdown files dir
*/
public
void
importMarkdownDir
(
final
File
markdownsDir
)
{
LOGGER
.
debug
(
"Import directory ["
+
markdownsDir
.
getPath
()
+
"]"
);
final
String
adminId
=
admin
.
optString
(
Keys
.
OBJECT_ID
);
final
JSONObject
admin
=
userQueryService
.
getAdmin
();
if
(
null
==
admin
)
{
// Not init yet
return
;
}
int
succCnt
=
0
,
failCnt
=
0
;
final
Set
<
String
>
failSet
=
new
TreeSet
<>();
final
Collection
<
File
>
mds
=
FileUtils
.
listFiles
(
markdownsPath
,
new
String
[]{
"md"
},
true
);
if
(
mds
.
isEmpty
())
{
return
;
}
final
String
adminId
=
admin
.
optString
(
Keys
.
OBJECT_ID
);
for
(
final
File
md
:
mds
)
{
final
String
fileName
=
md
.
getName
();
if
(
StringUtils
.
equalsIgnoreCase
(
fileName
,
"README.md"
))
{
continue
;
}
int
succCnt
=
0
,
failCnt
=
0
;
final
Set
<
String
>
failSet
=
new
TreeSet
<>();
final
Collection
<
File
>
mds
=
FileUtils
.
listFiles
(
markdownsDir
,
new
String
[]{
"md"
},
true
);
if
(
mds
.
isEmpty
())
{
return
;
}
for
(
final
File
md
:
mds
)
{
final
String
fileName
=
md
.
getName
();
if
(
StringUtils
.
equalsIgnoreCase
(
fileName
,
"README.md"
))
{
continue
;
}
try
{
final
String
fileContent
=
FileUtils
.
readFileToString
(
md
,
"UTF-8"
);
final
JSONObject
article
=
parseArticle
(
fileName
,
fileContent
);
article
.
put
(
Article
.
ARTICLE_AUTHOR_ID
,
adminId
);
try
{
final
String
fileContent
=
FileUtils
.
readFileToString
(
md
,
"UTF-8"
);
final
JSONObject
article
=
parseArticle
(
fileName
,
fileContent
);
article
.
put
(
Article
.
ARTICLE_AUTHOR_ID
,
adminId
);
final
JSONObject
request
=
new
JSONObject
();
request
.
put
(
Article
.
ARTICLE
,
article
);
final
JSONObject
request
=
new
JSONObject
();
request
.
put
(
Article
.
ARTICLE
,
article
);
final
String
id
=
articleMgmtService
.
addArticle
(
request
);
FileUtils
.
moveFile
(
md
,
new
File
(
md
.
getPath
()
+
"."
+
id
));
LOGGER
.
info
(
"Imported article ["
+
article
.
optString
(
Article
.
ARTICLE_TITLE
)
+
"]"
);
succCnt
++;
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
ERROR
,
"Import file ["
+
fileName
+
"] failed"
,
e
);
final
String
id
=
articleMgmtService
.
addArticle
(
request
);
FileUtils
.
moveFile
(
md
,
new
File
(
md
.
getPath
()
+
"."
+
id
));
LOGGER
.
info
(
"Imported article ["
+
article
.
optString
(
Article
.
ARTICLE_TITLE
)
+
"]"
);
succCnt
++;
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
ERROR
,
"Import file ["
+
fileName
+
"] failed"
,
e
);
failCnt
++;
failSet
.
add
(
fileName
);
}
failCnt
++;
failSet
.
add
(
fileName
);
}
}
if
(
0
==
succCnt
&&
0
==
failCnt
)
{
return
;
}
if
(
0
==
succCnt
&&
0
==
failCnt
)
{
return
;
}
final
StringBuilder
logBuilder
=
new
StringBuilder
();
logBuilder
.
append
(
"["
).
append
(
succCnt
).
append
(
"] imported, ["
).
append
(
failCnt
).
append
(
"] failed"
);
if
(
failCnt
>
0
)
{
logBuilder
.
append
(
": "
).
append
(
Strings
.
LINE_SEPARATOR
);
final
StringBuilder
logBuilder
=
new
StringBuilder
();
logBuilder
.
append
(
"["
).
append
(
succCnt
).
append
(
"] imported, ["
).
append
(
failCnt
).
append
(
"] failed"
);
if
(
failCnt
>
0
)
{
logBuilder
.
append
(
": "
).
append
(
Strings
.
LINE_SEPARATOR
);
for
(
final
String
fail
:
failSet
)
{
logBuilder
.
append
(
" "
).
append
(
fail
).
append
(
Strings
.
LINE_SEPARATOR
);
}
}
else
{
logBuilder
.
append
(
" :p"
);
for
(
final
String
fail
:
failSet
)
{
logBuilder
.
append
(
" "
).
append
(
fail
).
append
(
Strings
.
LINE_SEPARATOR
);
}
LOGGER
.
info
(
logBuilder
.
toString
());
}).
start
();
}
else
{
logBuilder
.
append
(
" :p"
);
}
LOGGER
.
info
(
logBuilder
.
toString
());
}
private
JSONObject
parseArticle
(
final
String
fileName
,
String
fileContent
)
{
...
...
src/main/resources/admin/admin-others.ftl
View file @
da595c87
...
...
@@ -23,6 +23,11 @@
<a href="#tools/others/data">${exportDataLabel}</a>
</div>
</li>
<li>
<div id="tabOthers_data">
<a href="#tools/others/import-data">${importDataLabel}</a>
</div>
</li>
<li>
<div id="tabOthers_log">
<a href="#tools/others/log">${viewLogLabel}</a>
...
...
@@ -42,6 +47,10 @@
<button class="fn__margin12" onclick="admin.others.exportJSON();">${exportJSONLabel}</button>
<button class="fn__margin12" onclick="admin.others.exportHexo();">${exportHexoLabel}</button>
</div>
<div id="tabOthersPanel_import-data" class="fn__none">
TODO
<button class="fn__margin12" onclick="">${uploadMarkdownZipLabel}</button>
</div>
<div id="tabOthersPanel_log" class="fn__none form">
<textarea rows="32" readonly></textarea>
</div>
...
...
src/main/resources/lang_en_US.properties
View file @
da595c87
...
...
@@ -18,6 +18,7 @@
# Author: Dongxu Wang
#
uploadMarkdownZipLabel
=
Upload Markdown Zip
editorModeSVLabel
=
Split View
editorModeIRLabel
=
Instant Rendering
editorModeWYSIWYGLabel
=
WYSIWYG
...
...
@@ -55,6 +56,7 @@ getUploadTokenErrLabel=Get community file storage service upload token failed
startToUseLabel
=
Start
clearDataLabel
=
Clear data
exportDataLabel
=
Export data
importDataLabel
=
Import data
syncToCommunityLabel
=
Sync to community
cntLabel
=
reply1Label
=
Reply
...
...
src/main/resources/lang_zh_CN.properties
View file @
da595c87
...
...
@@ -18,6 +18,7 @@
# Author: Dongxu Wang
#
uploadMarkdownZipLabel
=
\u
4E0A
\u
4F20 Markdown Zip
\u5305
editorModeSVLabel
=
\u5206\u
5C4F
\u9884\u
89C8
editorModeIRLabel
=
\u5373\u
65F6
\u
6E32
\u
67D3
editorModeWYSIWYGLabel
=
\u6240\u
89C1
\u5373\u6240\u
5F97
...
...
@@ -55,6 +56,7 @@ getUploadTokenErrLabel=\u83B7\u53D6\u793E\u533A\u6587\u4EF6\u5B58\u50A8\u670D\u5
startToUseLabel
=
\u
5F00
\u
59CB
\u
4F7F
\u7528
clearDataLabel
=
\u6570\u
636E
\u
6E05
\u7406
exportDataLabel
=
\u6570\u
636E
\u
5BFC
\u
51FA
importDataLabel
=
\u6570\u
636E
\u
5BFC
\u5165
syncToCommunityLabel
=
\u
540C
\u
6B65
\u5230\u
793E
\u
533A
cntLabel
=
\u
4E2A
reply1Label
=
\u
56DE
\u
590D
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment