├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── LICENSE
├── README.md
├── _config.yml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── org
│ │ └── code4everything
│ │ └── qiniu
│ │ ├── QiniuApplication.java
│ │ ├── api
│ │ ├── SdkConfigurer.java
│ │ └── SdkManager.java
│ │ ├── constant
│ │ └── QiniuValueConsts.java
│ │ ├── controller
│ │ └── MainController.java
│ │ ├── model
│ │ ├── BucketBean.java
│ │ ├── ConfigBean.java
│ │ └── FileBean.java
│ │ ├── service
│ │ └── QiniuService.java
│ │ └── util
│ │ ├── ConfigUtils.java
│ │ ├── DialogUtils.java
│ │ ├── QiniuDialog.java
│ │ └── QiniuUtils.java
└── resources
│ ├── image
│ └── qiniu.png
│ ├── log4j.properties
│ └── view
│ └── Main.fxml
└── test
└── java
└── org
└── code4everything
└── qiniu
├── FormatterTest.java
├── GsonTest.java
├── QiniuApplicationTest.java
└── RegexpTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | logs/*
3 | config.json
4 |
5 | # Log file
6 | *.log
7 |
8 | # BlueJ files
9 | *.ctxt
10 |
11 | # Mobile Tools for Java (J2ME)
12 | .mtj.tmp/
13 |
14 | # Package Files #
15 | *.jar
16 | *.war
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | target/
26 | pom.xml.tag
27 | pom.xml.releaseBackup
28 | pom.xml.versionsBackup
29 | pom.xml.next
30 | release.properties
31 | dependency-reduced-pom.xml
32 | buildNumber.properties
33 | .mvn/timing.properties
34 |
35 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
36 | !/.mvn/wrapper/maven-wrapper.jar
37 |
38 | ### IntelliJ IDEA ###
39 | .idea
40 | *.iws
41 | *.iml
42 | *.ipr
43 |
44 | .DS_Store
45 | !.mvn/wrapper/maven-wrapper.jar
46 |
47 | ### STS ###
48 | .apt_generated
49 | .classpath
50 | .factorypath
51 | .project
52 | .settings
53 | .springBeans
54 |
55 | ### NetBeans ###
56 | nbproject/private/
57 | build/
58 | nbbuild/
59 | dist/
60 | nbdist/
61 | .nb-gradle/
62 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/code4everything/qiniu/284253327473fc51e952b75db605719a096472e6/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 潘滔
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 欢迎体验我们全新的桌面端效率工具
2 |
3 | **欢迎体验我们全新的桌面端效率工具[RunFlow](https://myrest.top/myflow)。**
4 |
5 | > [https://myrest.top/myflow](https://myrest.top/myflow)
6 |
7 | ### 本仓库已停止更新,项目已迁移至[这里](https://gitee.com/code4everything/wetool-plugin)
8 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-hacker
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Migwn, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
204 | echo $MAVEN_PROJECTBASEDIR
205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
206 |
207 | # For Cygwin, switch paths to Windows format before running java
208 | if $cygwin; then
209 | [ -n "$M2_HOME" ] &&
210 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
211 | [ -n "$JAVA_HOME" ] &&
212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
213 | [ -n "$CLASSPATH" ] &&
214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
215 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
217 | fi
218 |
219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
220 |
221 | exec "$JAVACMD" \
222 | $MAVEN_OPTS \
223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
226 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
84 | @REM Fallback to current working directory if not found.
85 |
86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
88 |
89 | set EXEC_DIR=%CD%
90 | set WDIR=%EXEC_DIR%
91 | :findBaseDir
92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
93 | cd ..
94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
95 | set WDIR=%CD%
96 | goto findBaseDir
97 |
98 | :baseDirFound
99 | set MAVEN_PROJECTBASEDIR=%WDIR%
100 | cd "%EXEC_DIR%"
101 | goto endDetectBaseDir
102 |
103 | :baseDirNotFound
104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
105 | cd "%EXEC_DIR%"
106 |
107 | :endDetectBaseDir
108 |
109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
110 |
111 | @setlocal EnableExtensions EnableDelayedExpansion
112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
114 |
115 | :endReadAdditionalConfig
116 |
117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
118 |
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
123 | if ERRORLEVEL 1 goto error
124 | goto end
125 |
126 | :error
127 | set ERROR_CODE=1
128 |
129 | :end
130 | @endlocal & set ERROR_CODE=%ERROR_CODE%
131 |
132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
136 | :skipRcPost
137 |
138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
140 |
141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
142 |
143 | exit /B %ERROR_CODE%
144 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.zhazhapan
7 | qiniu
8 | 1.0.8
9 | jar
10 |
11 | qiniu
12 | 七牛同步工具
13 |
14 |
15 | UTF-8
16 | UTF-8
17 | 1.8
18 |
19 |
20 |
21 |
22 | com.qiniu
23 | qiniu-java-sdk
24 | [7.2.0, 7.2.99]
25 |
26 |
27 | com.zhazhapan
28 | util
29 | 1.1.1
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | 1.18.2
35 |
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 |
44 | 1.8
45 | 1.8
46 |
47 |
48 |
49 | org.apache.maven.plugins
50 | maven-shade-plugin
51 | 2.3
52 |
53 |
54 | package
55 |
56 | shade
57 |
58 |
59 |
60 |
62 | org.code4everything.qiniu.QiniuApplication
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/QiniuApplication.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu;
2 |
3 | import com.zhazhapan.util.ThreadPool;
4 | import javafx.application.Application;
5 | import javafx.fxml.FXMLLoader;
6 | import javafx.scene.Scene;
7 | import javafx.scene.control.ButtonType;
8 | import javafx.scene.image.Image;
9 | import javafx.scene.layout.VBox;
10 | import javafx.stage.Stage;
11 | import org.apache.log4j.Logger;
12 | import org.code4everything.qiniu.constant.QiniuValueConsts;
13 | import org.code4everything.qiniu.model.ConfigBean;
14 | import org.code4everything.qiniu.util.ConfigUtils;
15 | import org.code4everything.qiniu.util.DialogUtils;
16 |
17 | import java.util.Optional;
18 | import java.util.concurrent.LinkedBlockingQueue;
19 |
20 | /**
21 | * @author pantao
22 | */
23 | public class QiniuApplication extends Application {
24 |
25 | private static final Logger LOGGER = Logger.getLogger(QiniuApplication.class);
26 |
27 | private static Stage stage = null;
28 |
29 | private static ConfigBean configBean;
30 |
31 | public static Stage getStage() {
32 | return stage;
33 | }
34 |
35 | public static ConfigBean getConfigBean() {
36 | return configBean;
37 | }
38 |
39 | public static void setConfigBean(ConfigBean configBean) {
40 | QiniuApplication.configBean = configBean;
41 | }
42 |
43 | /**
44 | * 主程序入口
45 | */
46 | public static void main(String[] args) {
47 | // 设置线程池大小
48 | ThreadPool.setMaximumPoolSize(10);
49 | // 设置线程池最大排队大小
50 | ThreadPool.setWorkQueue(new LinkedBlockingQueue<>(1024));
51 | ThreadPool.init();
52 | // 启动 JavaFX 应用
53 | launch(args);
54 | }
55 |
56 | /**
57 | * 由 JavaFX 调用
58 | */
59 | @Override
60 | public void start(Stage stage) {
61 | try {
62 | // 加载视图页面
63 | VBox root = FXMLLoader.load(getClass().getResource(QiniuValueConsts.QINIU_VIEW_URL));
64 | Scene scene = new Scene(root);
65 | stage.setScene(scene);
66 | } catch (Exception e) {
67 | LOGGER.error("init stage error: " + e.getMessage());
68 | DialogUtils.showFatalError(QiniuValueConsts.INIT_APP_ERROR_HEADER, e);
69 | }
70 | // 设置图标
71 | stage.getIcons().add(new Image(getClass().getResourceAsStream("/image/qiniu.png")));
72 | stage.setTitle(QiniuValueConsts.MAIN_TITLE);
73 | // 设置关闭窗口事件
74 | stage.setOnCloseRequest(event -> {
75 | Optional result = DialogUtils.showConfirmation(QiniuValueConsts.CONFIRM_EXIT);
76 | if (result.isPresent() && result.get() != ButtonType.OK) {
77 | // 取消退出事件
78 | event.consume();
79 | return;
80 | }
81 | // 退出程序
82 | ThreadPool.executor.shutdown();
83 | System.exit(0);
84 | });
85 | QiniuApplication.stage = stage;
86 | stage.show();
87 | // 加载配置文件
88 | ConfigUtils.loadConfig();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/api/SdkConfigurer.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.api;
2 |
3 | import com.qiniu.cdn.CdnManager;
4 | import com.qiniu.common.Zone;
5 | import com.qiniu.storage.BucketManager;
6 | import com.qiniu.storage.Configuration;
7 | import com.qiniu.storage.UploadManager;
8 | import com.qiniu.storage.persistent.FileRecorder;
9 | import com.qiniu.util.Auth;
10 | import com.zhazhapan.util.Utils;
11 | import org.apache.log4j.Logger;
12 |
13 | import java.io.IOException;
14 | import java.nio.file.Paths;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 |
18 | /**
19 | * @author pantao
20 | */
21 | public class SdkConfigurer {
22 |
23 | private static final String[] BUCKET_NAME_ARRAY = {"华东", "华北", "华南", "北美"};
24 |
25 | private static final Map ZONE = new HashMap<>();
26 |
27 | private static final Logger LOGGER = Logger.getLogger(SdkConfigurer.class);
28 |
29 | private static Auth auth = null;
30 |
31 | private static UploadManager uploadManager = null;
32 |
33 | private static BucketManager bucketManager = null;
34 |
35 | private static CdnManager cdnManager = null;
36 |
37 | static {
38 | // 加载空间区域
39 | ZONE.put(BUCKET_NAME_ARRAY[0], Zone.zone0());
40 | ZONE.put(BUCKET_NAME_ARRAY[1], Zone.zone1());
41 | ZONE.put(BUCKET_NAME_ARRAY[2], Zone.zone2());
42 | ZONE.put(BUCKET_NAME_ARRAY[3], Zone.zoneNa0());
43 | }
44 |
45 | private SdkConfigurer() {}
46 |
47 | public static CdnManager getCdnManager() {
48 | return cdnManager;
49 | }
50 |
51 | public static BucketManager getBucketManager() {
52 | return bucketManager;
53 | }
54 |
55 | public static UploadManager getUploadManager() {
56 | return uploadManager;
57 | }
58 |
59 | public static Auth getAuth() {
60 | return auth;
61 | }
62 |
63 | /**
64 | * 创建上传需要的Auth
65 | */
66 | public static void createAuth(String accessKey, String secretKey) {
67 | auth = Auth.create(accessKey, secretKey);
68 | cdnManager = new CdnManager(auth);
69 | }
70 |
71 | /**
72 | * 配置文件上传环境,不再做网络检查,请执行保证网络通畅
73 | */
74 | public static boolean configUploadEnv(String zone, String bucket) {
75 | // 构造一个带指定Zone对象的配置类
76 | Configuration configuration = new Configuration(SdkConfigurer.ZONE.get(zone));
77 | // 生成上传凭证,然后准备上传
78 | String workDir = Paths.get(Utils.getCurrentWorkDir(), bucket).toString();
79 | try {
80 | FileRecorder fileRecorder = new FileRecorder(workDir);
81 | uploadManager = new UploadManager(configuration, fileRecorder);
82 | } catch (IOException e) {
83 | LOGGER.warn("load work directory failed, can't use file recorder");
84 | uploadManager = new UploadManager(configuration);
85 | }
86 | bucketManager = new BucketManager(auth, configuration);
87 | return true;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/api/SdkManager.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.api;
2 |
3 | import com.qiniu.cdn.CdnResult;
4 | import com.qiniu.cdn.CdnResult.LogData;
5 | import com.qiniu.common.QiniuException;
6 | import com.qiniu.http.Response;
7 | import com.qiniu.storage.BucketManager;
8 | import com.qiniu.storage.model.BatchStatus;
9 |
10 | import java.util.Map;
11 |
12 | /**
13 | * @author pantao
14 | */
15 | public class SdkManager {
16 |
17 | /**
18 | * 自定义私有链接过期时间
19 | */
20 | private static final long EXPIRE_IN_SECONDS = 24 * 60 * 60L;
21 |
22 | /**
23 | * 文件列表大小
24 | */
25 | private static final int LIST_SIZE = 1000;
26 |
27 | /**
28 | * 获取空间带宽统计
29 | */
30 | public CdnResult.BandwidthResult getBandwidthData(String[] domains, String startDate, String endDate) throws QiniuException {
31 | return SdkConfigurer.getCdnManager().getBandwidthData(domains, startDate, endDate, "day");
32 | }
33 |
34 | /**
35 | * 获取空间的流量统计
36 | */
37 | public CdnResult.FluxResult getFluxData(String[] domains, String startDate, String endDate) throws QiniuException {
38 | return SdkConfigurer.getCdnManager().getFluxData(domains, startDate, endDate, "day");
39 | }
40 |
41 | /**
42 | * 日志下载,CDN 相关
43 | */
44 | public Map listCdnLog(String[] domains, String logDate) throws QiniuException {
45 | return SdkConfigurer.getCdnManager().getCdnLogList(domains, logDate).data;
46 | }
47 |
48 | /**
49 | * 刷新文件,CDN 相关
50 | */
51 | public void refreshFile(String[] files) throws QiniuException {
52 | // 单次方法调用刷新的链接不可以超过100个
53 | SdkConfigurer.getCdnManager().refreshUrls(files);
54 | }
55 |
56 | /**
57 | * 私有下载
58 | */
59 | public String getPrivateUrl(String publicUrl) {
60 | return SdkConfigurer.getAuth().privateDownloadUrl(publicUrl, EXPIRE_IN_SECONDS);
61 | }
62 |
63 | /**
64 | * 更新镜像源
65 | */
66 | public void prefetch(String bucket, String key) throws QiniuException {
67 | SdkConfigurer.getBucketManager().prefetch(bucket, key);
68 | }
69 |
70 | /**
71 | * 设置文件生存时间
72 | */
73 | public void deleteAfterDays(String bucket, String key, int days) throws QiniuException {
74 | SdkConfigurer.getBucketManager().deleteAfterDays(bucket, key, days);
75 | }
76 |
77 | /**
78 | * 重命名文件
79 | */
80 | public void renameFile(String bucket, String oldName, String newName) throws QiniuException {
81 | moveFile(bucket, oldName, bucket, newName);
82 | }
83 |
84 | /**
85 | * 移动文件
86 | */
87 | public void moveFile(String srcBucket, String fromKey, String destBucket, String toKey) throws QiniuException {
88 | moveOrCopyFile(srcBucket, fromKey, destBucket, toKey, FileAction.MOVE);
89 | }
90 |
91 | /**
92 | * 移动或复制文件
93 | */
94 | public void moveOrCopyFile(String srcBucket, String srcKey, String destBucket, String destKey,
95 | FileAction fileAction) throws QiniuException {
96 | if (FileAction.COPY == fileAction) {
97 | SdkConfigurer.getBucketManager().copy(srcBucket, srcKey, destBucket, destKey, true);
98 | } else {
99 | SdkConfigurer.getBucketManager().move(srcBucket, srcKey, destBucket, destKey, true);
100 | }
101 | }
102 |
103 | /**
104 | * 修改文件类型
105 | */
106 | public void changeMime(String fileName, String newType, String bucket) throws QiniuException {
107 | SdkConfigurer.getBucketManager().changeMime(bucket, fileName, newType);
108 | }
109 |
110 | /**
111 | * 批量删除文件,单次批量请求的文件数量不得超过1000
112 | */
113 | public BatchStatus[] batchDelete(String bucket, String[] keys) throws QiniuException {
114 | BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
115 | batchOperations.addDeleteOp(bucket, keys);
116 | Response response = SdkConfigurer.getBucketManager().batch(batchOperations);
117 | return response.jsonToObject(BatchStatus[].class);
118 | }
119 |
120 | /**
121 | * 获取空间文件列表
122 | */
123 | public BucketManager.FileListIterator getFileListIterator(String bucket) {
124 | return SdkConfigurer.getBucketManager().createFileListIterator(bucket, "", LIST_SIZE, "");
125 | }
126 |
127 | public enum FileAction {
128 | // 复制或移动文件
129 | COPY, MOVE
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/constant/QiniuValueConsts.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.constant;
2 |
3 | import com.zhazhapan.util.Utils;
4 |
5 | import java.io.File;
6 |
7 | /**
8 | * 常量类
9 | *
10 | * @author pantao
11 | */
12 | public class QiniuValueConsts {
13 |
14 | public static final String CONFIG_PATH = Utils.getCurrentWorkDir() + File.separator + "config.json";
15 |
16 | public static final String QINIU_VIEW_URL = "/view/Main.fxml";
17 |
18 | public static final String QINIU_KEY_URL = "https://portal.qiniu.com/user/key";
19 |
20 | public static final String MAIN_TITLE = "七牛云管理工具";
21 |
22 | public static final String INIT_APP_ERROR_HEADER = "初始化错误,无法继续运行";
23 |
24 | public static final String OK = "确定";
25 |
26 | public static final String CANCEL = "取消";
27 |
28 | public static final String BUCKET_NAME = "空间名称";
29 |
30 | public static final String BUCKET_ZONE_NAME = "存储区域";
31 |
32 | public static final String BUCKET_URL = "空间域名";
33 |
34 | public static final String[] BUCKET_NAME_ARRAY = {"华东", "华北", "华南", "北美"};
35 |
36 | public static final String FILE_CHOOSER_TITLE = "选择需要上传的文件";
37 |
38 | public static final String OPEN_FILE_ERROR = "打开文件失败";
39 |
40 | public static final String UPLOAD_ERROR = "上传文件失败";
41 |
42 | public static final String UPLOADING = "文件上传中,请耐心等待。。。。。。\r\n";
43 |
44 | public static final String NEED_CHOOSE_BUCKET_OR_FILE = "请先选择一个存储空间或文件";
45 |
46 | public static final String CONFIG_UPLOAD_ENVIRONMENT = "正在配置文件上传环境,请耐心等待。。。。。。\r\n";
47 |
48 | public static final String RELOAD_CONFIG = "是否重新载入配置文件?";
49 |
50 | public static final String DOMAIN_CONFIG_ERROR = "您还没有正确地配置空间域名";
51 |
52 | public static final String REFRESH_SUCCESS = "刷新资源列表成功";
53 |
54 | public static final String DELETE_ERROR = "删除文件时发生异常";
55 |
56 | public static final String CHANGE_FILE_TYPE_ERROR = "删除文件发生异常";
57 |
58 | public static final String MOVE_OR_RENAME_ERROR = "移动或重命名文件失败";
59 |
60 | public static final String FILE_NAME = "文件名";
61 |
62 | public static final String COPY_AS = "保存文件副本";
63 |
64 | public static final String FILE_LIFE = "文件生存时间(天)";
65 |
66 | public static final String UPDATE_ERROR = "更新镜像源失败";
67 |
68 | public static final String DEFAULT_FILE_LIFE = "365";
69 |
70 | public static final String CONFIG_DOWNLOAD_PATH = "配置文件下载路径";
71 |
72 | public static final String INPUT_LOG_DATE = "请输入日志的日期";
73 |
74 | public static final String BUCKET_FLUX_ERROR = "获取空间流量统计失败";
75 |
76 | public static final String BUCKET_BAND_ERROR = "获取空间带宽统计失败";
77 |
78 | public static final String BUCKET_FLUX_COUNT = "空间流量(KB)";
79 |
80 | public static final String BUCKET_BANDWIDTH_COUNT = "空间带宽(KB)";
81 |
82 | public static final long DATE_SPAN_OF_THIRTY_ONE = 31 * 24 * 60 * 60 * 1000L;
83 |
84 | public static final String CONFIRM_EXIT = "确定退出?";
85 |
86 | private QiniuValueConsts() {}
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/controller/MainController.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.controller;
2 |
3 | import cn.hutool.core.date.DateUtil;
4 | import cn.hutool.core.util.StrUtil;
5 | import com.qiniu.common.QiniuException;
6 | import com.zhazhapan.util.Checker;
7 | import com.zhazhapan.util.Formatter;
8 | import com.zhazhapan.util.ThreadPool;
9 | import com.zhazhapan.util.Utils;
10 | import javafx.application.Platform;
11 | import javafx.collections.FXCollections;
12 | import javafx.collections.ObservableList;
13 | import javafx.fxml.FXML;
14 | import javafx.scene.chart.AreaChart;
15 | import javafx.scene.control.*;
16 | import javafx.scene.control.Label;
17 | import javafx.scene.control.TextArea;
18 | import javafx.scene.control.TextField;
19 | import javafx.scene.control.cell.PropertyValueFactory;
20 | import javafx.scene.control.cell.TextFieldTableCell;
21 | import javafx.scene.input.DragEvent;
22 | import javafx.scene.input.TransferMode;
23 | import javafx.stage.FileChooser;
24 | import javafx.util.Pair;
25 | import org.code4everything.qiniu.QiniuApplication;
26 | import org.code4everything.qiniu.api.SdkConfigurer;
27 | import org.code4everything.qiniu.api.SdkManager;
28 | import org.code4everything.qiniu.constant.QiniuValueConsts;
29 | import org.code4everything.qiniu.model.FileBean;
30 | import org.code4everything.qiniu.service.QiniuService;
31 | import org.code4everything.qiniu.util.ConfigUtils;
32 | import org.code4everything.qiniu.util.DialogUtils;
33 | import org.code4everything.qiniu.util.QiniuDialog;
34 | import org.code4everything.qiniu.util.QiniuUtils;
35 |
36 | import java.awt.*;
37 | import java.io.File;
38 | import java.time.LocalDate;
39 | import java.util.ArrayList;
40 | import java.util.Date;
41 | import java.util.List;
42 | import java.util.Optional;
43 | import java.util.regex.Pattern;
44 |
45 | /**
46 | * 界面控制类
47 | *
48 | * @author pantao
49 | */
50 | public class MainController {
51 |
52 | private static final String UPLOAD_STATUS_TEMPLATE = "{}\tsuccess\t{}{}\t{}";
53 |
54 | private static MainController mainController = null;
55 |
56 | private final QiniuService service = new QiniuService();
57 |
58 | private final QiniuDialog dialog = new QiniuDialog();
59 |
60 | @FXML
61 | public ComboBox bucketCB;
62 |
63 | @FXML
64 | public TextField zoneTF;
65 |
66 | @FXML
67 | public TextArea uploadStatusTA;
68 |
69 | @FXML
70 | public ComboBox prefixCB;
71 |
72 | @FXML
73 | public TableView resTV;
74 |
75 | @FXML
76 | public TextField searchTF;
77 |
78 | @FXML
79 | public CheckBox recursiveCB;
80 |
81 | @FXML
82 | public CheckBox keepPathCB;
83 |
84 | private ObservableList resData = null;
85 |
86 | /**
87 | * 空间总文件数
88 | */
89 | private int dataLength = 0;
90 |
91 | /**
92 | * 空间使用总大小
93 | */
94 | private long dataSize = 0;
95 |
96 | @FXML
97 | private TextArea selectedFileTA;
98 |
99 | @FXML
100 | private TextField domainTF;
101 |
102 | @FXML
103 | private TableColumn nameTC;
104 |
105 | @FXML
106 | private TableColumn typeTC;
107 |
108 | @FXML
109 | private TableColumn sizeTC;
110 |
111 | @FXML
112 | private TableColumn timeTC;
113 |
114 | @FXML
115 | private Label sizeLabel;
116 |
117 | @FXML
118 | private Label lengthLabel;
119 |
120 | @FXML
121 | private AreaChart fluxAC;
122 |
123 | @FXML
124 | private AreaChart bandwidthAC;
125 |
126 | @FXML
127 | private DatePicker startDP;
128 |
129 | @FXML
130 | private DatePicker endDP;
131 |
132 | @FXML
133 | private ComboBox fluxUnitCB;
134 |
135 | @FXML
136 | private ComboBox bandwidthUnitCB;
137 |
138 | private String status = "";
139 |
140 | /**
141 | * 父文件夹路径
142 | */
143 | private List rootPath = new ArrayList<>();
144 |
145 | public static MainController getInstance() {
146 | return mainController;
147 | }
148 |
149 | public ObservableList getResData() {
150 | return resData;
151 | }
152 |
153 | public void setResData(ObservableList resData) {
154 | this.resData = resData;
155 | }
156 |
157 | public int getDataLength() {
158 | return dataLength;
159 | }
160 |
161 | public void setDataLength(int dataLength) {
162 | this.dataLength = dataLength;
163 | }
164 |
165 | public long getDataSize() {
166 | return dataSize;
167 | }
168 |
169 | public void setDataSize(long dataSize) {
170 | this.dataSize = dataSize;
171 | }
172 |
173 | /**
174 | * 初始化
175 | */
176 | @FXML
177 | private void initialize() {
178 | mainController = this;
179 | nameTC.setCellValueFactory(new PropertyValueFactory<>("name"));
180 | // 设置文件名可编辑
181 | nameTC.setCellFactory(TextFieldTableCell.forTableColumn());
182 | nameTC.setOnEditCommit(value -> {
183 | String name;
184 | FileBean fileBean = value.getTableView().getItems().get(value.getTablePosition().getRow());
185 | // 编辑后重命名文件
186 | if (service.renameFile(bucketCB.getValue(), value.getOldValue(), value.getNewValue())) {
187 | name = value.getNewValue();
188 | } else {
189 | name = value.getOldValue();
190 | }
191 | if (Checker.isNotEmpty(searchTF.getText())) {
192 | resData.get(resData.indexOf(fileBean)).setName(name);
193 | }
194 | fileBean.setName(name);
195 | });
196 | typeTC.setCellValueFactory(new PropertyValueFactory<>("type"));
197 | // 设置文件类型可编辑
198 | typeTC.setCellFactory(TextFieldTableCell.forTableColumn());
199 | typeTC.setOnEditCommit(value -> {
200 | String type;
201 | FileBean fileBean = value.getTableView().getItems().get(value.getTablePosition().getRow());
202 | // 编辑后更新文件类型
203 | if (service.changeType(fileBean.getName(), value.getNewValue(), bucketCB.getValue())) {
204 | type = value.getNewValue();
205 | } else {
206 | type = value.getOldValue();
207 | }
208 | if (Checker.isNotEmpty(searchTF.getText())) {
209 | resData.get(resData.indexOf(fileBean)).setType(type);
210 | }
211 | fileBean.setType(type);
212 | });
213 | sizeTC.setCellValueFactory(new PropertyValueFactory<>("size"));
214 | timeTC.setCellValueFactory(new PropertyValueFactory<>("time"));
215 | // 设置表格允许多选
216 | resTV.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
217 | // 设置默认的开始和结束日期,并事件刷新数据
218 | endDP.setValue(LocalDate.now());
219 | long startTime = System.currentTimeMillis() - QiniuValueConsts.DATE_SPAN_OF_THIRTY_ONE;
220 | LocalDate localEndDate = Formatter.dateToLocalDate(new Date(startTime));
221 | startDP.setValue(localEndDate);
222 | // 设置桶下拉框改变事件,改变后配置新的上传环境
223 | bucketCB.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
224 | zoneTF.setText(QiniuApplication.getConfigBean().getZone(newValue));
225 | searchTF.clear();
226 | String url = QiniuApplication.getConfigBean().getUrl(newValue);
227 | if (Checker.isHyperLink(url)) {
228 | domainTF.setText(url);
229 | } else {
230 | domainTF.setText(QiniuValueConsts.DOMAIN_CONFIG_ERROR);
231 | }
232 | ThreadPool.executor.submit(() -> {
233 | if (SdkConfigurer.configUploadEnv(QiniuApplication.getConfigBean().getZone(newValue), newValue)) {
234 | // 加载文件列表
235 | mapResourceData();
236 | // 刷新流量带宽统计
237 | dateChange();
238 | }
239 | });
240 | });
241 | // 初始化统计单位选择框
242 | fluxUnitCB.getItems().addAll("KB", "MB", "GB", "TB");
243 | fluxUnitCB.setValue("KB");
244 | fluxUnitCB.getSelectionModel().selectedItemProperty().addListener((obs, o, n) -> drawChart(true, false));
245 | bandwidthUnitCB.getItems().addAll(fluxUnitCB.getItems());
246 | bandwidthUnitCB.setValue("KB");
247 | bandwidthUnitCB.getSelectionModel().selectedItemProperty().addListener((obs, o, n) -> drawChart(false, true));
248 | }
249 |
250 | /**
251 | * 开始拖曳文件
252 | */
253 | public void dragFileOver(DragEvent event) {
254 | event.acceptTransferModes(TransferMode.ANY);
255 | }
256 |
257 | /**
258 | * 拖曳文件松开鼠标
259 | */
260 | public void dragFileDropped(DragEvent event) {
261 | appendFile(event.getDragboard().getFiles());
262 | }
263 |
264 | /**
265 | * 开始日期或结束日期改变,刷新流量、带宽统计
266 | */
267 | public void dateChange() {
268 | drawChart(true, true);
269 | }
270 |
271 | /**
272 | * 绘制数据统计图表
273 | */
274 | private void drawChart(boolean isFluxUnitChange, boolean isBandwidthUnitChange) {
275 | Date localStartDate = Formatter.localDateToDate(startDP.getValue());
276 | Date localEndDate = Formatter.localDateToDate(endDP.getValue());
277 | // 将本地日期装换成字符串
278 | String fromDate = Formatter.dateToString(localStartDate);
279 | String toDate = Formatter.dateToString(localEndDate);
280 | // 获取开始日期和结束日期的时间差
281 | long timeSpan = localEndDate.getTime() - localStartDate.getTime();
282 | if (Checker.isNotEmpty(domainTF.getText()) && timeSpan >= 0 && timeSpan <= QiniuValueConsts.DATE_SPAN_OF_THIRTY_ONE) {
283 | Platform.runLater(() -> {
284 | String[] domains = {domainTF.getText()};
285 | if (isFluxUnitChange) {
286 | // 获取流量数据
287 | String fluxUnit = fluxUnitCB.getValue();
288 | fluxAC.getData().clear();
289 | fluxAC.getData().add(service.getBucketFlux(domains, fromDate, toDate, fluxUnit));
290 | }
291 | if (isBandwidthUnitChange) {
292 | // 获取带宽数据
293 | String bandUnit = bandwidthUnitCB.getValue();
294 | bandwidthAC.getData().clear();
295 | bandwidthAC.getData().add(service.getBucketBandwidth(domains, fromDate, toDate, bandUnit));
296 | }
297 | });
298 | }
299 | }
300 |
301 | /**
302 | * 下载日志
303 | */
304 | public void downloadCdnLog() {
305 | String date = DialogUtils.showInputDialog(null, QiniuValueConsts.INPUT_LOG_DATE,
306 | Formatter.dateToString(new Date()));
307 | service.downloadCdnLog(date);
308 | }
309 |
310 | /**
311 | * 刷新文件
312 | */
313 | public void refreshFile() {
314 | service.refreshFile(resTV.getSelectionModel().getSelectedItems(), domainTF.getText());
315 | }
316 |
317 | /**
318 | * 用浏览器打开文件
319 | */
320 | public void openFile() {
321 | ObservableList selectedItems = resTV.getSelectionModel().getSelectedItems();
322 | if (Checker.isNotEmpty(selectedItems)) {
323 | String filename = selectedItems.get(0).getName();
324 | QiniuUtils.openLink(QiniuUtils.buildUrl(filename, domainTF.getText()));
325 | }
326 | }
327 |
328 | /**
329 | * 私有下载
330 | */
331 | public void privateDownload() {
332 | download(DownloadWay.PRIVATE);
333 | }
334 |
335 | /**
336 | * 下载文件
337 | */
338 | private void download(DownloadWay way) {
339 | ObservableList selectedItems = resTV.getSelectionModel().getSelectedItems();
340 | if (Checker.isNotEmpty(selectedItems)) {
341 | if (way == DownloadWay.PUBLIC) {
342 | selectedItems.forEach(bean -> service.publicDownload(bean.getName(), domainTF.getText()));
343 | } else {
344 | selectedItems.forEach(bean -> service.privateDownload(bean.getName(), domainTF.getText()));
345 | }
346 | }
347 | }
348 |
349 | /**
350 | * 公有下载
351 | */
352 | public void publicDownload() {
353 | download(DownloadWay.PUBLIC);
354 | }
355 |
356 | /**
357 | * 更新镜像源
358 | */
359 | public void updateFile() {
360 | ObservableList selectedItems = resTV.getSelectionModel().getSelectedItems();
361 | if (Checker.isNotEmpty(selectedItems)) {
362 | selectedItems.forEach(bean -> service.updateFile(bucketCB.getValue(), bean.getName()));
363 | }
364 | }
365 |
366 | /**
367 | * 设置文件生存时间
368 | */
369 | public void setLife() {
370 | ObservableList selectedItems = resTV.getSelectionModel().getSelectedItems();
371 | if (Checker.isNotEmpty(selectedItems)) {
372 | // 弹出输入框
373 | String fileLife = DialogUtils.showInputDialog(null, QiniuValueConsts.FILE_LIFE,
374 | QiniuValueConsts.DEFAULT_FILE_LIFE);
375 | if (Checker.isNumber(fileLife)) {
376 | int life = Formatter.stringToInt(fileLife);
377 | selectedItems.forEach(bean -> service.setFileLife(bucketCB.getValue(), bean.getName(), life));
378 | }
379 | }
380 | }
381 |
382 | /**
383 | * 显示移动或复制文件的弹窗
384 | */
385 | public void showFileMovableDialog() {
386 | ObservableList selectedItems = resTV.getSelectionModel().getSelectedItems();
387 | if (Checker.isEmpty(selectedItems)) {
388 | // 没有选择文件,结束方法
389 | return;
390 | }
391 | Pair resultPair;
392 | String bucket = bucketCB.getValue();
393 | if (selectedItems.size() > 1) {
394 | resultPair = dialog.showFileDialog(bucket, "", false);
395 | } else {
396 | resultPair = dialog.showFileDialog(bucket, selectedItems.get(0).getName(), true);
397 | }
398 | if (Checker.isNotNull(resultPair)) {
399 | boolean useNewKey = Checker.isNotEmpty(resultPair.getValue()[1]);
400 | ObservableList fileBeans = resTV.getItems();
401 | for (FileBean fileBean : selectedItems) {
402 | String fromBucket = bucketCB.getValue();
403 | String toBucket = resultPair.getValue()[0];
404 | String name = useNewKey ? resultPair.getValue()[1] : fileBean.getName();
405 | boolean isSuccess = service.moveOrCopyFile(fromBucket, fileBean.getName(), toBucket, name,
406 | resultPair.getKey());
407 | if (resultPair.getKey() == SdkManager.FileAction.MOVE && isSuccess) {
408 | boolean isInSearch = Checker.isNotEmpty(searchTF.getText());
409 | if (fromBucket.equals(toBucket)) {
410 | // 更新文件名
411 | fileBean.setName(name);
412 | if (isInSearch) {
413 | fileBeans.get(fileBeans.indexOf(fileBean)).setName(name);
414 | }
415 | } else {
416 | // 删除数据源
417 | fileBeans.remove(fileBean);
418 | dataLength--;
419 | dataSize -= Formatter.sizeToLong(fileBean.getSize());
420 | if (isInSearch) {
421 | fileBeans.remove(fileBean);
422 | }
423 | }
424 | }
425 | }
426 | countBucket();
427 | }
428 | }
429 |
430 | /**
431 | * 删除文件
432 | */
433 | public void deleteFile() {
434 | service.deleteFile(resTV.getSelectionModel().getSelectedItems(), bucketCB.getValue());
435 | }
436 |
437 | /**
438 | * 复制链接
439 | */
440 | public void copyLink() {
441 | ObservableList fileBeans = resTV.getSelectionModel().getSelectedItems();
442 | if (Checker.isNotEmpty(fileBeans)) {
443 | // 只复制选中的第一个文件的链接
444 | Utils.copyToClipboard(QiniuUtils.buildUrl(fileBeans.get(0).getName(), domainTF.getText()));
445 | }
446 | }
447 |
448 | /**
449 | * 搜索资源文件,忽略大小写
450 | */
451 | public void searchFile() {
452 | ArrayList files = new ArrayList<>();
453 | String search = Checker.checkNull(searchTF.getText());
454 | dataLength = 0;
455 | dataSize = 0;
456 | // 正则匹配查询
457 | Pattern pattern = Pattern.compile(search, Pattern.CASE_INSENSITIVE);
458 | for (FileBean file : resData) {
459 | if (pattern.matcher(file.getName()).find()) {
460 | files.add(file);
461 | dataLength++;
462 | dataSize += Formatter.sizeToLong(file.getSize());
463 | }
464 | }
465 | countBucket();
466 | resTV.setItems(FXCollections.observableArrayList(files));
467 | }
468 |
469 | /**
470 | * 统计空间文件的数量以及大小
471 | */
472 | public void countBucket() {
473 | lengthLabel.setText(Formatter.customFormatDecimal(dataLength, ",###") + " 个文件");
474 | sizeLabel.setText(Formatter.formatSize(dataSize));
475 | }
476 |
477 | /**
478 | * 刷新资源列表
479 | */
480 | public void refreshResourceData() {
481 | mapResourceData();
482 | DialogUtils.showInformation(QiniuValueConsts.REFRESH_SUCCESS);
483 | }
484 |
485 | /**
486 | * 将从存储空间获取的文件列表映射到表中
487 | */
488 | private void mapResourceData() {
489 | ThreadPool.executor.submit(() -> {
490 | // 列出资源文件
491 | service.listFile();
492 | Platform.runLater(() -> {
493 | resTV.setItems(resData);
494 | countBucket();
495 | });
496 | });
497 |
498 | }
499 |
500 | /**
501 | * 添加桶至下拉框
502 | */
503 | public void appendBucket(String bucket) {
504 | if (!bucketCB.getItems().contains(bucket)) {
505 | bucketCB.getItems().add(bucket);
506 | }
507 | }
508 |
509 | /**
510 | * 保存文件的上传状态
511 | */
512 | public void saveUploadStatus() {
513 | FileChooser chooser = new FileChooser();
514 | chooser.setTitle(QiniuValueConsts.FILE_CHOOSER_TITLE);
515 | chooser.setInitialDirectory(new File(Utils.getCurrentWorkDir()));
516 | File file = chooser.showSaveDialog(QiniuApplication.getStage());
517 | QiniuUtils.saveFile(file, uploadStatusTA.getText());
518 | }
519 |
520 | /**
521 | * 复制文件上传状态至剪贴板
522 | */
523 | public void copyUploadStatus() {
524 | Utils.copyToClipboard(uploadStatusTA.getText());
525 | }
526 |
527 | /**
528 | * 清空文件的上传状态
529 | */
530 | public void clearUploadStatus() {
531 | uploadStatusTA.clear();
532 | }
533 |
534 | /**
535 | * 显示选择文件的弹窗
536 | */
537 | public void showOpenFileDialog() {
538 | FileChooser chooser = new FileChooser();
539 | chooser.setTitle(QiniuValueConsts.FILE_CHOOSER_TITLE);
540 | chooser.setInitialDirectory(new File(Utils.getCurrentWorkDir()));
541 | appendFile(chooser.showOpenMultipleDialog(QiniuApplication.getStage()));
542 | }
543 |
544 | /**
545 | * 添加上传的文件,支持拖曳文件夹
546 | */
547 | private void appendFile(List files) {
548 | if (Checker.isNotEmpty(files)) {
549 | File[] fileArray = new File[files.size()];
550 | appendFile(files.toArray(fileArray), false);
551 | }
552 | }
553 |
554 | /**
555 | * 添加上传的文件,支持拖曳文件夹
556 | */
557 | private void appendFile(File[] files, boolean isRecursive) {
558 | if (Checker.isNotNull(files)) {
559 | for (File file : files) {
560 | if (file.isDirectory()) {
561 | if (isRecursive) {
562 | // 递归添加文件
563 | if (recursiveCB.isSelected()) {
564 | appendFile(file.listFiles(), true);
565 | }
566 | } else {
567 | rootPath.add(file.getAbsolutePath());
568 | appendFile(file.listFiles(), true);
569 | }
570 | } else if (!selectedFileTA.getText().contains(file.getAbsolutePath())) {
571 | selectedFileTA.insertText(0, file.getAbsolutePath() + "\r\n");
572 | }
573 | }
574 | }
575 | }
576 |
577 | /**
578 | * 上传选择的文件
579 | */
580 | public void uploadFile() {
581 | if (Checker.isEmpty(zoneTF.getText()) || Checker.isEmpty(selectedFileTA.getText())) {
582 | // 没有选择存储空间或文件,不能上传文件
583 | DialogUtils.showWarning(QiniuValueConsts.NEED_CHOOSE_BUCKET_OR_FILE);
584 | return;
585 | }
586 | // 新建一个线程上传文件的线程
587 | ThreadPool.executor.submit(() -> {
588 | Platform.runLater(() -> uploadStatusTA.insertText(0, QiniuValueConsts.CONFIG_UPLOAD_ENVIRONMENT));
589 | String bucket = bucketCB.getValue();
590 | // 默认不指定KEY的情况下,以文件内容的哈希值作为文件名
591 | String key = Checker.checkNull(prefixCB.getValue());
592 | String[] paths = selectedFileTA.getText().split("\n");
593 | // 去掉\r\n的长度
594 | int endIndex = QiniuValueConsts.UPLOADING.length() - 2;
595 | Platform.runLater(() -> uploadStatusTA.deleteText(0,
596 | QiniuValueConsts.CONFIG_UPLOAD_ENVIRONMENT.length() - 1));
597 | // 总文件数
598 | for (String path : paths) {
599 | if (Checker.isNotEmpty(path)) {
600 | Platform.runLater(() -> uploadStatusTA.insertText(0, QiniuValueConsts.UPLOADING));
601 | String filename = "";
602 | String url = "http://" + QiniuApplication.getConfigBean().getUrl(bucket) + "/";
603 | File file = new File(path);
604 | try {
605 | // 判断文件是否存在
606 | if (file.exists()) {
607 | // 保持文件相对父文件夹的路径
608 | if (keepPathCB.isSelected() && Checker.isNotEmpty(rootPath)) {
609 | for (String root : rootPath) {
610 | if (file.getAbsolutePath().startsWith(root)) {
611 | String postKey = root.substring(root.lastIndexOf(File.separator) + 1);
612 | filename = key + postKey + file.getAbsolutePath().substring(root.length());
613 | break;
614 | }
615 | }
616 | }
617 | if (Checker.isEmpty(filename)) {
618 | filename = key + file.getName();
619 | }
620 | service.uploadFile(bucket, path, filename);
621 | String now = DateUtil.formatDate(new Date());
622 | status = StrUtil.format(UPLOAD_STATUS_TEMPLATE, now, url, filename, path);
623 | } else if (Checker.isHyperLink(path)) {
624 | // 抓取网络文件到空间中
625 | filename = key + QiniuUtils.getFileName(path);
626 | SdkConfigurer.getBucketManager().fetch(path, bucket, filename);
627 | String now = DateUtil.formatDate(new Date());
628 | status = StrUtil.format(UPLOAD_STATUS_TEMPLATE, now, url, filename, path);
629 | } else {
630 | // 文件不存在
631 | status = DateUtil.formatDate(new Date()) + "\tfailed\t" + path;
632 | }
633 | } catch (QiniuException e) {
634 | status = DateUtil.formatDate(new Date()) + "\terror\t" + path;
635 | Platform.runLater(() -> DialogUtils.showException(QiniuValueConsts.UPLOAD_ERROR, e));
636 | }
637 | Platform.runLater(() -> {
638 | uploadStatusTA.deleteText(0, endIndex);
639 | uploadStatusTA.insertText(0, status);
640 | });
641 | }
642 | Platform.runLater(() -> selectedFileTA.deleteText(0, path.length() + (paths.length > 1 ? 1 : 0)));
643 | }
644 | rootPath.clear();
645 | Platform.runLater(() -> {
646 | // 将光标移到最前面
647 | uploadStatusTA.positionCaret(0);
648 | // 清空待上传的文件列表
649 | selectedFileTA.clear();
650 | });
651 | mapResourceData();
652 | // 添加文件前缀到配置文件
653 | savePrefix(key);
654 | });
655 | }
656 |
657 | /**
658 | * 保存前缀
659 | */
660 | private void savePrefix(String key) {
661 | if (Checker.isNotEmpty(key) && !QiniuApplication.getConfigBean().getPrefixes().contains(key)) {
662 | Platform.runLater(() -> prefixCB.getItems().add(key));
663 | QiniuApplication.getConfigBean().getPrefixes().add(key);
664 | ConfigUtils.writeConfig();
665 | }
666 | }
667 |
668 | /**
669 | * 打开配置文件
670 | */
671 | public void openConfigFile() {
672 | try {
673 | Desktop.getDesktop().open(new File(QiniuValueConsts.CONFIG_PATH));
674 | // 用户触发是否重载配置文件
675 | Optional result = DialogUtils.showConfirmation(QiniuValueConsts.RELOAD_CONFIG);
676 | if (result.isPresent() && result.get() == ButtonType.OK) {
677 | // 重新载入配置文件
678 | bucketCB.getItems().clear();
679 | prefixCB.getItems().clear();
680 | ConfigUtils.loadConfig();
681 | }
682 | } catch (Exception e) {
683 | DialogUtils.showException(QiniuValueConsts.OPEN_FILE_ERROR, e);
684 | }
685 | }
686 |
687 | /**
688 | * 显示重置密钥的弹窗
689 | */
690 | public void showKeyDialog() {
691 | boolean ok = dialog.showKeyDialog();
692 | if (ok && Checker.isNotEmpty(zoneTF.getText())) {
693 | // 配置新的环境
694 | SdkConfigurer.configUploadEnv(zoneTF.getText(), bucketCB.getValue());
695 | }
696 | }
697 |
698 | /**
699 | * 显示添加存储空间的弹窗
700 | */
701 | public void showBucketDialog() {
702 | dialog.showBucketDialog();
703 | }
704 |
705 | public enum DownloadWay {
706 | // 下载的方式,包括私有和公有
707 | PRIVATE, PUBLIC
708 | }
709 | }
710 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/model/BucketBean.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | * 桶信息
11 | *
12 | * @author pantao
13 | * @since 2018/11/13
14 | */
15 | @Data
16 | @AllArgsConstructor
17 | @NoArgsConstructor
18 | public class BucketBean implements Serializable {
19 |
20 | private String bucket;
21 |
22 | private String zone;
23 |
24 | private String url;
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/model/ConfigBean.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.model;
2 |
3 | import cn.hutool.core.collection.CollectionUtil;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 | import java.util.ArrayList;
10 | import java.util.Objects;
11 |
12 | /**
13 | * 应用配置信息
14 | *
15 | * @author pantao
16 | * @since 2018/11/12
17 | **/
18 | @Data
19 | @NoArgsConstructor
20 | @AllArgsConstructor
21 | public class ConfigBean implements Serializable {
22 |
23 | private String accessKey;
24 |
25 | private String secretKey;
26 |
27 | private ArrayList buckets;
28 |
29 | private ArrayList prefixes;
30 |
31 | private String storagePath;
32 |
33 | public String getBucket(String bucket) {
34 | BucketBean bucketBean = getBucketBean(bucket);
35 | return Objects.isNull(bucketBean) ? "" : bucketBean.getBucket();
36 | }
37 |
38 | public String getUrl(String bucket) {
39 | BucketBean bucketBean = getBucketBean(bucket);
40 | return Objects.isNull(bucketBean) ? "" : bucketBean.getUrl();
41 | }
42 |
43 | public String getZone(String bucket) {
44 | BucketBean bucketBean = getBucketBean(bucket);
45 | return Objects.isNull(bucketBean) ? "" : bucketBean.getZone();
46 | }
47 |
48 | public BucketBean getBucketBean(String bucket) {
49 | if (CollectionUtil.isNotEmpty(buckets)) {
50 | for (BucketBean bean : buckets) {
51 | if (Objects.equals(bean.getBucket(), bucket)) {
52 | return bean;
53 | }
54 | }
55 | }
56 | return null;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/model/FileBean.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | /**
8 | * 文件信息
9 | *
10 | * @author pantao
11 | */
12 | @Data
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | public class FileBean {
16 |
17 | private String name;
18 |
19 | private String type;
20 |
21 | private String size;
22 |
23 | private String time;
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/service/QiniuService.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.service;
2 |
3 | import com.qiniu.cdn.CdnResult;
4 | import com.qiniu.common.QiniuException;
5 | import com.qiniu.storage.BucketManager;
6 | import com.qiniu.storage.model.BatchStatus;
7 | import com.qiniu.storage.model.FileInfo;
8 | import com.zhazhapan.util.Checker;
9 | import com.zhazhapan.util.Formatter;
10 | import javafx.application.Platform;
11 | import javafx.collections.FXCollections;
12 | import javafx.collections.ObservableList;
13 | import javafx.scene.chart.XYChart;
14 | import org.apache.log4j.Logger;
15 | import org.code4everything.qiniu.QiniuApplication;
16 | import org.code4everything.qiniu.api.SdkConfigurer;
17 | import org.code4everything.qiniu.api.SdkManager;
18 | import org.code4everything.qiniu.constant.QiniuValueConsts;
19 | import org.code4everything.qiniu.controller.MainController;
20 | import org.code4everything.qiniu.model.FileBean;
21 | import org.code4everything.qiniu.util.DialogUtils;
22 | import org.code4everything.qiniu.util.QiniuUtils;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Map;
26 |
27 | /**
28 | * 七牛服务类
29 | *
30 | * @author pantao
31 | * @since 2018/11/13
32 | */
33 | public class QiniuService {
34 |
35 | private static final Logger LOGGER = Logger.getLogger(QiniuService.class);
36 |
37 | private final SdkManager sdkManager = new SdkManager();
38 |
39 | /**
40 | * 上传文件
41 | */
42 | public void uploadFile(String bucket, String key, String filename) throws QiniuException {
43 | String upToken = SdkConfigurer.getAuth().uploadToken(bucket, filename);
44 | SdkConfigurer.getUploadManager().put(key, filename, upToken);
45 | }
46 |
47 | /**
48 | * 获取空间文件列表
49 | */
50 | public void listFile() {
51 | MainController main = MainController.getInstance();
52 | // 列举空间文件列表
53 | BucketManager.FileListIterator iterator = sdkManager.getFileListIterator(main.bucketCB.getValue());
54 | ArrayList files = new ArrayList<>();
55 | main.setDataLength(0);
56 | main.setDataSize(0);
57 | // 处理结果
58 | while (iterator.hasNext()) {
59 | FileInfo[] items = iterator.next();
60 | for (FileInfo item : items) {
61 | main.setDataLength(main.getDataLength() + 1);
62 | main.setDataSize(main.getDataSize() + item.fsize);
63 | // 将七牛的时间单位(100纳秒)转换成毫秒,然后转换成时间
64 | String time = Formatter.timeStampToString(item.putTime / 10000);
65 | String size = Formatter.formatSize(item.fsize);
66 | FileBean file = new FileBean(item.key, item.mimeType, size, time);
67 | files.add(file);
68 | }
69 | }
70 | main.setResData(FXCollections.observableArrayList(files));
71 | }
72 |
73 | /**
74 | * 批量删除文件,单次批量请求的文件数量不得超过1000
75 | */
76 | public void deleteFile(ObservableList fileBeans, String bucket) {
77 | if (Checker.isNotEmpty(fileBeans) && QiniuUtils.checkNet()) {
78 | // 生成待删除的文件列表
79 | String[] files = new String[fileBeans.size()];
80 | ArrayList selectedFiles = new ArrayList<>();
81 | int i = 0;
82 | for (FileBean fileBean : fileBeans) {
83 | files[i++] = fileBean.getName();
84 | selectedFiles.add(fileBean);
85 | }
86 | try {
87 | BatchStatus[] batchStatusList = sdkManager.batchDelete(bucket, files);
88 | MainController main = MainController.getInstance();
89 | // 文件列表是否为搜索后结果
90 | boolean isInSearch = Checker.isNotEmpty(main.searchTF.getText());
91 | ObservableList currentRes = main.resTV.getItems();
92 | // 更新界面数据
93 | for (i = 0; i < files.length; i++) {
94 | BatchStatus status = batchStatusList[i];
95 | String file = files[i];
96 | if (status.code == 200) {
97 | main.getResData().remove(selectedFiles.get(i));
98 | main.setDataLength(main.getDataLength() - 1);
99 | main.setDataSize(main.getDataSize() - Formatter.sizeToLong(selectedFiles.get(i).getSize()));
100 | if (isInSearch) {
101 | currentRes.remove(selectedFiles.get(i));
102 | }
103 | } else {
104 | LOGGER.error("delete " + file + " failed, message -> " + status.data.error);
105 | DialogUtils.showError("删除文件:" + file + " 失败");
106 | }
107 | }
108 | } catch (QiniuException e) {
109 | DialogUtils.showException(QiniuValueConsts.DELETE_ERROR, e);
110 | }
111 | MainController.getInstance().countBucket();
112 | }
113 | }
114 |
115 | /**
116 | * 修改文件类型
117 | */
118 | public boolean changeType(String fileName, String newType, String bucket) {
119 | boolean result = true;
120 | try {
121 | sdkManager.changeMime(bucket, fileName, newType);
122 | } catch (QiniuException e) {
123 | DialogUtils.showException(QiniuValueConsts.CHANGE_FILE_TYPE_ERROR, e);
124 | result = false;
125 | }
126 | return result;
127 | }
128 |
129 | /**
130 | * 重命名文件
131 | */
132 | public boolean renameFile(String bucket, String oldName, String newName) {
133 | return moveFile(bucket, oldName, bucket, newName);
134 | }
135 |
136 | /**
137 | * 移动文件
138 | */
139 | private boolean moveFile(String srcBucket, String fromKey, String destBucket, String toKey) {
140 | return moveOrCopyFile(srcBucket, fromKey, destBucket, toKey, SdkManager.FileAction.MOVE);
141 | }
142 |
143 | /**
144 | * 移动或复制文件
145 | */
146 | public boolean moveOrCopyFile(String srcBucket, String srcKey, String destBucket, String destKey,
147 | SdkManager.FileAction fileAction) {
148 | boolean result = true;
149 | try {
150 | sdkManager.moveOrCopyFile(srcBucket, srcKey, destBucket, destKey, fileAction);
151 | } catch (QiniuException e) {
152 | LOGGER.error("move file failed, message -> " + e.getMessage());
153 | DialogUtils.showException(QiniuValueConsts.MOVE_OR_RENAME_ERROR, e);
154 | result = false;
155 | }
156 | return result;
157 | }
158 |
159 | /**
160 | * 设置文件生存时间
161 | */
162 | public void setFileLife(String bucket, String key, int days) {
163 | try {
164 | sdkManager.deleteAfterDays(bucket, key, days);
165 | LOGGER.info("set file life success");
166 | } catch (QiniuException e) {
167 | LOGGER.error("set file life error, message -> " + e.getMessage());
168 | DialogUtils.showException(QiniuValueConsts.MOVE_OR_RENAME_ERROR, e);
169 | }
170 | }
171 |
172 | /**
173 | * 更新镜像源
174 | */
175 | public void updateFile(String bucket, String key) {
176 | try {
177 | sdkManager.prefetch(bucket, key);
178 | LOGGER.info("prefetch files success");
179 | } catch (QiniuException e) {
180 | LOGGER.error("prefetch files error, message -> " + e.getMessage());
181 | DialogUtils.showException(QiniuValueConsts.UPDATE_ERROR, e);
182 | }
183 | }
184 |
185 | /**
186 | * 公有下载
187 | */
188 | public void publicDownload(String fileName, String domain) {
189 | QiniuUtils.download(QiniuUtils.buildUrl(fileName, domain));
190 | }
191 |
192 | /**
193 | * 私有下载
194 | */
195 | public void privateDownload(String fileName, String domain) {
196 | QiniuUtils.download(sdkManager.getPrivateUrl(QiniuUtils.buildUrl(fileName, domain)));
197 | }
198 |
199 | /**
200 | * 刷新文件
201 | */
202 | public void refreshFile(ObservableList fileBeans, String domain) {
203 | if (Checker.isNotEmpty(fileBeans)) {
204 | String[] files = new String[fileBeans.size()];
205 | int i = 0;
206 | // 获取公有链接
207 | for (FileBean fileBean : fileBeans) {
208 | files[i++] = QiniuUtils.buildUrl(fileBean.getName(), domain);
209 | }
210 | try {
211 | // 刷新文件
212 | sdkManager.refreshFile(files);
213 | } catch (QiniuException e) {
214 | LOGGER.error("refresh files error, message -> " + e.getMessage());
215 | DialogUtils.showException(e);
216 | }
217 | }
218 | }
219 |
220 | /**
221 | * 日志下载
222 | */
223 | public void downloadCdnLog(String logDate) {
224 | if (Checker.isNotEmpty(QiniuApplication.getConfigBean().getBuckets()) && Checker.isDate(logDate)) {
225 | // 转换域名成数组格式
226 | String[] domains = new String[QiniuApplication.getConfigBean().getBuckets().size()];
227 | for (int i = 0; i < QiniuApplication.getConfigBean().getBuckets().size(); i++) {
228 | domains[i] = QiniuApplication.getConfigBean().getBuckets().get(i).getUrl();
229 | }
230 | Map cdnLog = null;
231 | try {
232 | cdnLog = sdkManager.listCdnLog(domains, logDate);
233 | } catch (QiniuException e) {
234 | DialogUtils.showException(e);
235 | }
236 | if (Checker.isNotEmpty(cdnLog)) {
237 | // 下载日志
238 | for (Map.Entry logs : cdnLog.entrySet()) {
239 | for (CdnResult.LogData log : logs.getValue()) {
240 | QiniuUtils.download(log.url);
241 | }
242 | }
243 | }
244 | }
245 | }
246 |
247 |
248 | /**
249 | * 获取空间带宽统计,使用自定义单位
250 | */
251 | public XYChart.Series getBucketBandwidth(String[] domains, String startDate, String endDate,
252 | String unit) {
253 | // 获取带宽数据
254 | CdnResult.BandwidthResult bandwidthResult = null;
255 | try {
256 | bandwidthResult = sdkManager.getBandwidthData(domains, startDate, endDate);
257 | } catch (QiniuException e) {
258 | Platform.runLater(() -> DialogUtils.showException(QiniuValueConsts.BUCKET_BAND_ERROR, e));
259 | }
260 | // 设置图表
261 | XYChart.Series series = new XYChart.Series<>();
262 | series.setName(QiniuValueConsts.BUCKET_BANDWIDTH_COUNT.replaceAll("[A-Z]+", unit));
263 | // 格式化数据
264 | if (Checker.isNotNull(bandwidthResult) && Checker.isNotEmpty(bandwidthResult.data)) {
265 | long unitSize = Formatter.sizeToLong("1 " + unit);
266 | for (Map.Entry bandwidth : bandwidthResult.data.entrySet()) {
267 | CdnResult.BandwidthData bandwidthData = bandwidth.getValue();
268 | if (Checker.isNotNull(bandwidthData)) {
269 | setSeries(bandwidthResult.time, bandwidthData.china, bandwidthData.oversea, series, unitSize);
270 | }
271 | }
272 | }
273 | return series;
274 | }
275 |
276 | /**
277 | * 获取空间的流量统计,使用自定义单位
278 | */
279 | public XYChart.Series getBucketFlux(String[] domains, String startDate, String endDate, String unit) {
280 | // 获取流量数据
281 | CdnResult.FluxResult fluxResult = null;
282 | try {
283 | fluxResult = sdkManager.getFluxData(domains, startDate, endDate);
284 | } catch (QiniuException e) {
285 | Platform.runLater(() -> DialogUtils.showException(QiniuValueConsts.BUCKET_FLUX_ERROR, e));
286 | }
287 | // 设置图表
288 | XYChart.Series series = new XYChart.Series<>();
289 | series.setName(QiniuValueConsts.BUCKET_FLUX_COUNT.replaceAll("[A-Z]+", unit));
290 | // 格式化数据
291 | if (Checker.isNotNull(fluxResult) && Checker.isNotEmpty(fluxResult.data)) {
292 | long unitSize = Formatter.sizeToLong("1 " + unit);
293 | for (Map.Entry flux : fluxResult.data.entrySet()) {
294 | CdnResult.FluxData fluxData = flux.getValue();
295 | if (Checker.isNotNull(fluxData)) {
296 | setSeries(fluxResult.time, fluxData.china, fluxData.oversea, series, unitSize);
297 | }
298 | }
299 | }
300 | return series;
301 | }
302 |
303 | /**
304 | * 处理带宽数据
305 | */
306 | private void setSeries(String[] times, Long[] china, Long[] oversea, XYChart.Series series,
307 | long unit) {
308 | int i = 0;
309 | for (String time : times) {
310 | long size = 0;
311 | if (Checker.isNotEmpty(china)) {
312 | size += china[i];
313 | }
314 | if (Checker.isNotEmpty(oversea)) {
315 | size += oversea[i];
316 | }
317 | series.getData().add(new XYChart.Data<>(time.substring(5, 10), size / unit));
318 | i++;
319 | }
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/util/ConfigUtils.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.util;
2 |
3 | import cn.hutool.core.collection.CollectionUtil;
4 | import cn.hutool.core.io.FileUtil;
5 | import cn.hutool.core.util.ObjectUtil;
6 | import cn.hutool.core.util.StrUtil;
7 | import com.alibaba.fastjson.JSONObject;
8 | import javafx.application.Platform;
9 | import org.code4everything.qiniu.QiniuApplication;
10 | import org.code4everything.qiniu.api.SdkConfigurer;
11 | import org.code4everything.qiniu.constant.QiniuValueConsts;
12 | import org.code4everything.qiniu.controller.MainController;
13 | import org.code4everything.qiniu.model.BucketBean;
14 | import org.code4everything.qiniu.model.ConfigBean;
15 |
16 | import java.util.ArrayList;
17 |
18 | /**
19 | * 配置文件工具类
20 | *
21 | * @author pantao
22 | * @since 2018/11/12
23 | **/
24 | public class ConfigUtils {
25 |
26 | private static final String CONFIG_PATH = QiniuValueConsts.CONFIG_PATH;
27 |
28 | private ConfigUtils() {}
29 |
30 | /**
31 | * 加载配置文件
32 | */
33 | public static void loadConfig() {
34 | QiniuApplication.setConfigBean(new ConfigBean());
35 | if (FileUtil.exist(CONFIG_PATH)) {
36 | ConfigBean config = JSONObject.parseObject(FileUtil.readUtf8String(CONFIG_PATH), ConfigBean.class);
37 | if (ObjectUtil.isNotNull(config)) {
38 | QiniuApplication.setConfigBean(config);
39 | if (StrUtil.isNotEmpty(config.getAccessKey()) && StrUtil.isNotEmpty(config.getSecretKey())) {
40 | // 创建上传权限
41 | SdkConfigurer.createAuth(config.getAccessKey(), config.getSecretKey());
42 | }
43 | MainController controller = MainController.getInstance();
44 | if (CollectionUtil.isEmpty(config.getBuckets())) {
45 | // 设置一个空的桶列表,防止出现空指针
46 | config.setBuckets(new ArrayList<>());
47 | } else {
48 | Platform.runLater(() -> {
49 | // 添加桶
50 | config.getBuckets().forEach(bucket -> controller.appendBucket(bucket.getBucket()));
51 | // 选中第一个桶
52 | BucketBean bucket = config.getBuckets().get(0);
53 | controller.bucketCB.setValue(bucket.getBucket());
54 | controller.zoneTF.setText(bucket.getZone());
55 | });
56 | }
57 | if (CollectionUtil.isEmpty(config.getPrefixes())) {
58 | // 设置一个空的前缀列表,防止出现空指针
59 | config.setPrefixes(new ArrayList<>());
60 | } else {
61 | // 添加前缀
62 | Platform.runLater(() -> config.getPrefixes().forEach(prefix -> controller.prefixCB.getItems().add(prefix)));
63 | }
64 | return;
65 | }
66 | }
67 | // 设置一个空的配置对象,防止出现空指针
68 | ConfigBean configBean = new ConfigBean();
69 | configBean.setPrefixes(new ArrayList<>());
70 | configBean.setBuckets(new ArrayList<>());
71 | QiniuApplication.setConfigBean(configBean);
72 | writeConfig();
73 | }
74 |
75 | /**
76 | * 写配置文件
77 | */
78 | public static void writeConfig() {
79 | FileUtil.writeUtf8String(JSONObject.toJSONString(QiniuApplication.getConfigBean(), true), CONFIG_PATH);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/util/DialogUtils.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.util;
2 |
3 | import javafx.scene.control.Alert;
4 | import javafx.scene.control.Alert.AlertType;
5 | import javafx.scene.control.ButtonType;
6 | import javafx.scene.control.TextArea;
7 | import javafx.scene.control.TextInputDialog;
8 | import javafx.scene.layout.GridPane;
9 | import javafx.scene.layout.Priority;
10 | import javafx.stage.Modality;
11 | import javafx.stage.StageStyle;
12 | import javafx.stage.Window;
13 | import org.code4everything.qiniu.constant.QiniuValueConsts;
14 |
15 | import java.io.PrintWriter;
16 | import java.io.StringWriter;
17 | import java.util.Optional;
18 |
19 | /**
20 | * 弹窗工具类
21 | *
22 | * @author pantao 对JavaFX对话框进行封装
23 | */
24 | public class DialogUtils {
25 |
26 | private DialogUtils() {}
27 |
28 | public static String showInputDialog(String header, String content, String defaultValue) {
29 | TextInputDialog dialog = new TextInputDialog(defaultValue);
30 | dialog.setTitle(QiniuValueConsts.MAIN_TITLE);
31 | dialog.setHeaderText(header);
32 | dialog.setContentText(content);
33 | Optional result = dialog.showAndWait();
34 | return result.orElse(null);
35 | }
36 |
37 | public static Optional showInformation(String content) {
38 | return showInformation(null, content);
39 | }
40 |
41 | public static Optional showInformation(String header, String content) {
42 | return showAlert(header, content, AlertType.INFORMATION);
43 | }
44 |
45 | public static Optional showWarning(String content) {
46 | return showWarning(null, content);
47 | }
48 |
49 | public static Optional showWarning(String header, String content) {
50 | return showAlert(header, content, AlertType.WARNING);
51 | }
52 |
53 | public static Optional showError(String content) {
54 | return showError(null, content);
55 | }
56 |
57 | public static Optional showError(String header, String content) {
58 | return showAlert(header, content, AlertType.ERROR);
59 | }
60 |
61 | public static Optional showConfirmation(String content) {
62 | return showConfirmation(null, content);
63 | }
64 |
65 | public static Optional showConfirmation(String header, String content) {
66 | return showAlert(header, content, AlertType.CONFIRMATION);
67 | }
68 |
69 | public static Optional showException(Exception e) {
70 | return showException(null, e);
71 | }
72 |
73 | public static void showFatalError(String header, Exception e) {
74 | showException(header, e);
75 | System.exit(0);
76 | }
77 |
78 | public static Optional showException(String header, Exception e) {
79 | // 获取一个警告对象
80 | Alert alert = getAlert(header, "错误信息追踪:", AlertType.ERROR);
81 | // 打印异常信息
82 | StringWriter stringWriter = new StringWriter();
83 | PrintWriter printWriter = new PrintWriter(stringWriter);
84 | e.printStackTrace(printWriter);
85 | String exception = stringWriter.toString();
86 | // 显示异常信息
87 | TextArea textArea = new TextArea(exception);
88 | textArea.setEditable(false);
89 | textArea.setWrapText(true);
90 | // 设置弹窗容器
91 | textArea.setMaxWidth(Double.MAX_VALUE);
92 | textArea.setMaxHeight(Double.MAX_VALUE);
93 | GridPane.setVgrow(textArea, Priority.ALWAYS);
94 | GridPane.setHgrow(textArea, Priority.ALWAYS);
95 | GridPane gridPane = new GridPane();
96 | gridPane.setMaxWidth(Double.MAX_VALUE);
97 | gridPane.add(textArea, 0, 0);
98 | alert.getDialogPane().setExpandableContent(gridPane);
99 | return alert.showAndWait();
100 | }
101 |
102 | public static Optional showAlert(String content) {
103 | return showAlert(null, content);
104 | }
105 |
106 | public static Optional showAlert(String content, AlertType alertType) {
107 | return showAlert(null, content, alertType);
108 | }
109 |
110 | public static Optional showAlert(String header, String content) {
111 | return showAlert(header, content, AlertType.INFORMATION);
112 | }
113 |
114 | public static Optional showAlert(String header, String content, AlertType alertType) {
115 | return showAlert(header, content, alertType, Modality.NONE, null, StageStyle.DECORATED);
116 | }
117 |
118 | public static Optional showAlert(String header, String content, AlertType alertType,
119 | Modality modality, Window window, StageStyle style) {
120 | return getAlert(header, content, alertType, modality, window, style).showAndWait();
121 | }
122 |
123 | public static Alert getAlert(String header, String content, AlertType alertType) {
124 | return getAlert(header, content, alertType, Modality.APPLICATION_MODAL, null, StageStyle.DECORATED);
125 | }
126 |
127 | public static Alert getAlert(String header, String content, AlertType alertType, Modality modality, Window window
128 | , StageStyle style) {
129 | Alert alert = new Alert(alertType);
130 | alert.setTitle(QiniuValueConsts.MAIN_TITLE);
131 | alert.setHeaderText(header);
132 | alert.setContentText(content);
133 | alert.initModality(modality);
134 | alert.initOwner(window);
135 | alert.initStyle(style);
136 | return alert;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/util/QiniuDialog.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.util;
2 |
3 | import com.zhazhapan.util.Checker;
4 | import com.zhazhapan.util.dialog.Dialogs;
5 | import javafx.application.Platform;
6 | import javafx.scene.Node;
7 | import javafx.scene.control.*;
8 | import javafx.scene.layout.GridPane;
9 | import javafx.stage.Modality;
10 | import javafx.util.Pair;
11 | import org.code4everything.qiniu.QiniuApplication;
12 | import org.code4everything.qiniu.api.SdkConfigurer;
13 | import org.code4everything.qiniu.api.SdkManager;
14 | import org.code4everything.qiniu.constant.QiniuValueConsts;
15 | import org.code4everything.qiniu.controller.MainController;
16 | import org.code4everything.qiniu.model.BucketBean;
17 |
18 | import java.util.Optional;
19 |
20 | /**
21 | * 应用弹窗
22 | *
23 | * @author pantao
24 | * @since 2018/11/13
25 | */
26 | public class QiniuDialog {
27 |
28 | /**
29 | * 显示移动文件的弹窗
30 | */
31 | public Pair showFileDialog(String bucket, String key, boolean setKey) {
32 | MainController main = MainController.getInstance();
33 | ButtonType ok = new ButtonType(QiniuValueConsts.OK, ButtonBar.ButtonData.OK_DONE);
34 | Dialog dialog = getDialog(ok);
35 | // 文件名输入框
36 | TextField keyTextField = new TextField();
37 | keyTextField.setPrefWidth(300);
38 | keyTextField.setPromptText(QiniuValueConsts.FILE_NAME);
39 | keyTextField.setText(key);
40 | // 空间选择框
41 | ComboBox bucketCombo = new ComboBox<>();
42 | bucketCombo.getItems().addAll(main.bucketCB.getItems());
43 | bucketCombo.setValue(bucket);
44 | // 保存文件副本复选框
45 | CheckBox copyAsCheckBox = new CheckBox(QiniuValueConsts.COPY_AS);
46 | copyAsCheckBox.setSelected(true);
47 | // 设置容器
48 | GridPane grid = Dialogs.getGridPane();
49 | grid.add(copyAsCheckBox, 0, 0, 2, 1);
50 | grid.add(new Label(QiniuValueConsts.BUCKET_NAME), 0, 1);
51 | grid.add(bucketCombo, 1, 1);
52 | if (setKey) {
53 | // 显示文件名输入框
54 | grid.add(new Label(QiniuValueConsts.FILE_NAME), 0, 2);
55 | grid.add(keyTextField, 1, 2);
56 | Platform.runLater(keyTextField::requestFocus);
57 | }
58 | dialog.getDialogPane().setContent(grid);
59 | // 数据转换器
60 | dialog.setResultConverter(dialogButton -> {
61 | if (dialogButton == ok) {
62 | return new String[]{bucketCombo.getValue(), keyTextField.getText()};
63 | }
64 | return null;
65 | });
66 | // 读取数据
67 | Optional result = dialog.showAndWait();
68 | if (result.isPresent()) {
69 | bucket = bucketCombo.getValue();
70 | key = keyTextField.getText();
71 | SdkManager.FileAction action = copyAsCheckBox.isSelected() ? SdkManager.FileAction.COPY :
72 | SdkManager.FileAction.MOVE;
73 | return new Pair<>(action, new String[]{bucket, key});
74 | } else {
75 | return null;
76 | }
77 | }
78 |
79 | /**
80 | * 显示输入密钥的对话框
81 | *
82 | * @return 返回用户是否点击确定按钮
83 | */
84 | public boolean showKeyDialog() {
85 | ButtonType ok = new ButtonType(QiniuValueConsts.OK, ButtonBar.ButtonData.OK_DONE);
86 | Dialog dialog = getDialog(ok);
87 | // 文本框
88 | TextField ak = new TextField();
89 | ak.setMinWidth(400);
90 | ak.setPromptText("Access Key");
91 | TextField sk = new TextField();
92 | sk.setPromptText("Secret Key");
93 | // 设置超链接
94 | Hyperlink hyperlink = new Hyperlink("查看我的KEY:" + QiniuValueConsts.QINIU_KEY_URL);
95 | hyperlink.setOnAction(event -> QiniuUtils.openLink(QiniuValueConsts.QINIU_KEY_URL));
96 | // 设置容器
97 | GridPane grid = Dialogs.getGridPane();
98 | grid.add(hyperlink, 0, 0, 2, 1);
99 | grid.add(new Label("Access Key:"), 0, 1);
100 | grid.add(ak, 1, 1);
101 | grid.add(new Label("Secret Key:"), 0, 2);
102 | grid.add(sk, 1, 2);
103 | Node okButton = dialog.getDialogPane().lookupButton(ok);
104 | okButton.setDisable(true);
105 | dialog.getDialogPane().setContent(grid);
106 | Platform.runLater(ak::requestFocus);
107 | // 监听文本框的输入状态
108 | ak.textProperty().addListener((observable, oldValue, newValue) -> okButton.setDisable(newValue.trim().isEmpty() || sk.getText().trim().isEmpty()));
109 | sk.textProperty().addListener((observable, oldValue, newValue) -> okButton.setDisable(newValue.trim().isEmpty() || ak.getText().trim().isEmpty()));
110 | // 等待用户操作
111 | Optional result = dialog.showAndWait();
112 | // 处理结果
113 | if (result.isPresent() && Checker.isNotEmpty(ak.getText()) && Checker.isNotEmpty(sk.getText())) {
114 | QiniuApplication.getConfigBean().setAccessKey(ak.getText());
115 | QiniuApplication.getConfigBean().setSecretKey(sk.getText());
116 | SdkConfigurer.createAuth(ak.getText(), sk.getText());
117 | ConfigUtils.writeConfig();
118 | return true;
119 | }
120 | return false;
121 | }
122 |
123 | /**
124 | * 显示添加桶的弹窗
125 | */
126 | public void showBucketDialog() {
127 | ButtonType ok = new ButtonType(QiniuValueConsts.OK, ButtonBar.ButtonData.OK_DONE);
128 | Dialog dialog = getDialog(ok);
129 | // 桶名称输入框
130 | TextField bucket = new TextField();
131 | bucket.setPromptText(QiniuValueConsts.BUCKET_NAME);
132 | // 桶域名输入框
133 | TextField url = new TextField();
134 | url.setPromptText(QiniuValueConsts.BUCKET_URL);
135 | // 桶区域输入框
136 | ComboBox zone = new ComboBox<>();
137 | zone.getItems().addAll(QiniuValueConsts.BUCKET_NAME_ARRAY);
138 | zone.setValue(QiniuValueConsts.BUCKET_NAME_ARRAY[0]);
139 | // 设置容器
140 | GridPane grid = Dialogs.getGridPane();
141 | grid.add(new Label(QiniuValueConsts.BUCKET_NAME), 0, 0);
142 | grid.add(bucket, 1, 0);
143 | grid.add(new Label(QiniuValueConsts.BUCKET_URL), 0, 1);
144 | grid.add(url, 1, 1);
145 | grid.add(new Label(QiniuValueConsts.BUCKET_ZONE_NAME), 0, 2);
146 | grid.add(zone, 1, 2);
147 | Node okButton = dialog.getDialogPane().lookupButton(ok);
148 | okButton.setDisable(true);
149 | dialog.getDialogPane().setContent(grid);
150 | Platform.runLater(bucket::requestFocus);
151 | // 监听文本框的输入状态
152 | bucket.textProperty().addListener((observable, oldValue, newValue) -> okButton.setDisable(newValue.trim().isEmpty() || url.getText().isEmpty()));
153 | url.textProperty().addListener((observable, oldValue, newValue) -> okButton.setDisable(newValue.trim().isEmpty() || bucket.getText().isEmpty()));
154 | // 结果转换器
155 | dialog.setResultConverter(dialogButton -> {
156 | if (dialogButton == ok) {
157 | return new String[]{bucket.getText(), zone.getValue(), (Checker.isHyperLink(url.getText()) ?
158 | url.getText() : "example.com")};
159 | }
160 | return null;
161 | });
162 | // 等待用户操作
163 | Optional result = dialog.showAndWait();
164 | result.ifPresent(res -> {
165 | // 处理结果
166 | Platform.runLater(() -> MainController.getInstance().appendBucket(res[0]));
167 | BucketBean bucketBean = new BucketBean(res[0], res[1], res[2]);
168 | QiniuApplication.getConfigBean().getBuckets().add(bucketBean);
169 | ConfigUtils.writeConfig();
170 | });
171 | }
172 |
173 | private Dialog getDialog(ButtonType ok) {
174 | Dialog dialog = new Dialog<>();
175 | dialog.setTitle(QiniuValueConsts.MAIN_TITLE);
176 | dialog.setHeaderText(null);
177 | dialog.initModality(Modality.APPLICATION_MODAL);
178 | // 自定义确认和取消按钮
179 | ButtonType cancel = new ButtonType(QiniuValueConsts.CANCEL, ButtonBar.ButtonData.CANCEL_CLOSE);
180 | dialog.getDialogPane().getButtonTypes().addAll(ok, cancel);
181 | return dialog;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/main/java/org/code4everything/qiniu/util/QiniuUtils.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu.util;
2 |
3 | import cn.hutool.core.lang.Validator;
4 | import cn.hutool.http.HttpUtil;
5 | import com.zhazhapan.util.FileExecutor;
6 | import com.zhazhapan.util.Formatter;
7 | import com.zhazhapan.util.ThreadPool;
8 | import com.zhazhapan.util.Utils;
9 | import com.zhazhapan.util.dialog.Alerts;
10 | import org.apache.log4j.Logger;
11 | import org.code4everything.qiniu.QiniuApplication;
12 | import org.code4everything.qiniu.constant.QiniuValueConsts;
13 |
14 | import java.io.File;
15 | import java.io.IOException;
16 | import java.io.InputStream;
17 | import java.io.UnsupportedEncodingException;
18 | import java.net.URL;
19 | import java.net.URLEncoder;
20 |
21 | /**
22 | * @author pantao
23 | * @since 2018/4/14
24 | */
25 | public class QiniuUtils {
26 |
27 | private static final Logger LOGGER = Logger.getLogger(QiniuUtils.class);
28 |
29 | private static final String HTTP = "http";
30 |
31 | private QiniuUtils() {}
32 |
33 | /**
34 | * 下载文件
35 | *
36 | * @param url 文件链接
37 | */
38 | public static void download(String url) {
39 | // 验证存储路径
40 | if (Validator.isEmpty(QiniuApplication.getConfigBean().getStoragePath())) {
41 | // 显示存储路径输入框
42 | String storagePath = DialogUtils.showInputDialog(null, QiniuValueConsts.CONFIG_DOWNLOAD_PATH,
43 | Utils.getCurrentWorkDir());
44 | if (Validator.isEmpty(storagePath)) {
45 | return;
46 | }
47 | QiniuApplication.getConfigBean().setStoragePath(storagePath);
48 | ConfigUtils.writeConfig();
49 | }
50 | final String dest = QiniuApplication.getConfigBean().getStoragePath();
51 | // 下载文件
52 | ThreadPool.executor.execute(() -> HttpUtil.downloadFile(url, dest));
53 | }
54 |
55 | /**
56 | * 检查是否连接网络
57 | */
58 | public static boolean checkNet() {
59 | try {
60 | URL url = new URL("https://www.qiniu.com/");
61 | InputStream in = url.openStream();
62 | in.close();
63 | return true;
64 | } catch (IOException e) {
65 | LOGGER.error("there is no connection to the network");
66 | return false;
67 | }
68 | }
69 |
70 | public static void saveLogFile(String file, String content) {
71 | try {
72 | FileExecutor.saveLogFile(file, content);
73 | } catch (IOException e) {
74 | Alerts.showError(QiniuValueConsts.MAIN_TITLE, e.getMessage());
75 | }
76 | }
77 |
78 | public static void saveFile(File file, String content) {
79 | try {
80 | FileExecutor.saveFile(file, content);
81 | } catch (IOException e) {
82 | Alerts.showError(QiniuValueConsts.MAIN_TITLE, e.getMessage());
83 | }
84 | }
85 |
86 | public static void openLink(String url) {
87 | try {
88 | Utils.openLink(url);
89 | } catch (Exception e) {
90 | Alerts.showError(QiniuValueConsts.MAIN_TITLE, e.getMessage());
91 | }
92 | }
93 |
94 | public static String getFileName(String string) {
95 | try {
96 | return Formatter.getFileName(string);
97 | } catch (UnsupportedEncodingException e) {
98 | LOGGER.error("get file name of url failed, message -> " + e.getMessage());
99 | return "";
100 | }
101 | }
102 |
103 | /**
104 | * 拼接链接
105 | */
106 | public static String buildUrl(String fileName, String domain) {
107 | if (!domain.startsWith(HTTP)) {
108 | domain = HTTP + "://" + domain;
109 | }
110 | fileName = fileName.replaceAll(" ", "qn_code_per_20").replaceAll("/", "qn_code_per_2F");
111 | try {
112 | fileName = URLEncoder.encode(fileName, "utf-8").replaceAll("qn_code_per_2F", "/");
113 | return String.format("%s/%s", domain, fileName.replaceAll("qn_code_per_20", "%20"));
114 | } catch (UnsupportedEncodingException e) {
115 | LOGGER.error("encode url failed, message -> " + e.getMessage());
116 | return "";
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/resources/image/qiniu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/code4everything/qiniu/284253327473fc51e952b75db605719a096472e6/src/main/resources/image/qiniu.png
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootCategory=INFO, file
2 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
3 | log4j.appender.file.file=logs/qiniu
4 | log4j.appender.file.DatePattern='.'yyyy-MM-dd'.log'
5 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} %5p %c{1}:%L - %m%n
7 |
--------------------------------------------------------------------------------
/src/main/resources/view/Main.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
70 |
71 |
72 |
73 |
74 |
83 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
107 |
109 |
110 |
111 |
112 |
113 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
145 |
150 |
155 |
161 |
166 |
171 |
177 |
183 |
188 |
193 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
216 |
224 |
226 |
227 |
228 |
229 |
230 |
238 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
309 |
314 |
319 |
320 |
321 |
322 |
323 |
324 |
--------------------------------------------------------------------------------
/src/test/java/org/code4everything/qiniu/FormatterTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package org.code4everything.qiniu;
5 |
6 | import org.junit.Test;
7 |
8 | import com.zhazhapan.util.Formatter;
9 |
10 | /**
11 | * @author pantao
12 | *
13 | */
14 | public class FormatterTest {
15 |
16 | @Test
17 | public void testSizeToLong() {
18 | String[] sizes = { "23.12 MB", "12.89 KB", "23 B", "23.77 GB", "89.12 TB" };
19 | for (String size : sizes) {
20 | System.out.println(Formatter.sizeToLong(size));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/org/code4everything/qiniu/GsonTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package org.code4everything.qiniu;
5 |
6 | import org.junit.Test;
7 |
8 | import com.google.gson.JsonArray;
9 | import com.google.gson.JsonElement;
10 | import com.google.gson.JsonObject;
11 | import com.google.gson.JsonParser;
12 | import com.zhazhapan.util.Checker;
13 |
14 | /**
15 | * @author pantao
16 | *
17 | */
18 | public class GsonTest {
19 |
20 | public String configJson = "{accessKey:123456,secretKey:abcdef,buckets:[{bucket:zhazhapan,zone:华东}]}";
21 |
22 | @Test
23 | public void testGson() {
24 | JsonObject json = new JsonParser().parse(configJson).getAsJsonObject();
25 | JsonElement buckets = json.get("buckets");
26 | if (Checker.isNotNull(buckets)) {
27 | JsonArray array = buckets.getAsJsonArray();
28 | for (JsonElement element : array) {
29 | System.out.println(((JsonObject) element).get("bucket").getAsString());
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/test/java/org/code4everything/qiniu/QiniuApplicationTest.java:
--------------------------------------------------------------------------------
1 | package org.code4everything.qiniu;
2 |
3 | import org.junit.Test;
4 |
5 | /**
6 | * @author pantao
7 | */
8 |
9 | public class QiniuApplicationTest {
10 |
11 | @Test
12 | public void testContext() {
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/org/code4everything/qiniu/RegexpTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package org.code4everything.qiniu;
5 |
6 | import com.zhazhapan.util.Checker;
7 | import org.code4everything.qiniu.util.QiniuUtils;
8 | import org.junit.Test;
9 |
10 | /**
11 | * @author pantao
12 | */
13 | public class RegexpTest {
14 |
15 | @Test
16 | public void testGetFileName() {
17 | String[] files = {"http://oxns0wnsc.bkt.clouddn.com/fims/css/distpicker.css", "http://oxns0wnsc.bkt.clouddn"
18 | + ".com/fims/css/distpicker", "http://oxns0wnsc.bkt.clouddn.com/fims/css/easy-responsive-tabs.css",
19 | "http://oxns0wnsc.bkt.clouddn.com/zhazhapan/test/%E6%BD%98%E6%BB%94-18780459330-Java%E5%BC%80%E5%8F"
20 | + "%91.docx"};
21 | for (String file : files) {
22 | System.out.println(QiniuUtils.getFileName(file));
23 | }
24 | }
25 |
26 | @Test
27 | public void testHyperlink() {
28 | System.out.println(Checker.isHyperLink("https://portal.qiniu.com/bucket/zhazhapan/resource"));
29 | System.out.println(Checker.isHyperLink("http://portal.qiniu.com/bucket/zhazhapan/resource"));
30 | System.out.println(Checker.isHyperLink("portal.qiniu.com/bucket/zhazhapan/resource"));
31 | System.out.println(Checker.isHyperLink("oxns0wnsc.bkt.clouddn.com"));
32 | System.out.println(Checker.isHyperLink("hhttp://portal"));
33 | System.out.println(Checker.isHyperLink("https://cn.wordpress.org/wordpress-4.8.1-zh_CN.zip"));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------