Compare commits

..

No commits in common. "master" and "main" have entirely different histories.
master ... main

135 changed files with 6604 additions and 3037 deletions

View File

@ -1,7 +0,0 @@
param.ignore=@cn.wzpmc.filemanager.annotation.Address
param.ignore=@cn.wzpmc.filemanager.annotation.AuthorizationRequired
method.additional.header[@cn.wzpmc.filemanager.annotation.AuthorizationRequired]={name: "Authorization",value: "",description: "验证Token",required:true, example="eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImV4cCI6MTczNDA4NzM0Nn0.8EmG-u-yCLVdWtQRnfhsU5zqjIGR6vruqfI8CHba6VsBAom9gPzZz1juo1dproUItB6AXCpxMcPv1I0ggo-ZIw"}
method.additional.header[groovy:it.args().any { params -> params.hasAnn("cn.wzpmc.filemanager.annotation.AuthorizationRequired") }]={name: "Authorization",value: "",description: "验证Token",required:true, example="eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImV4cCI6MTczNDA4NzM0Nn0.8EmG-u-yCLVdWtQRnfhsU5zqjIGR6vruqfI8CHba6VsBAom9gPzZz1juo1dproUItB6AXCpxMcPv1I0ggo-ZIw"}
param.required=groovy:it.hasAnn("org.springframework.web.bind.annotation.RequestParam") ? it.ann("org.springframework.web.bind.annotation.RequestParam","defaultValue").equals("\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n") : true
method.return[#response]=groovy: helper.resolveLink(it.doc("response"))
ignore=#ignore

232
.gitignore vendored Normal file → Executable file
View File

@ -1,44 +1,192 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
# ---> Java
# Compiled class file
*.class
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Common build and run directionary
run/
# Log
# Log file
*.log
logs/
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
# ---> Node
# Logs
logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# ---> Vue
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
# TODO: where does this rule come from?
docs/_book
# TODO: where does this rule come from?
test/
# ---> Gradle
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
application.properties
run/

15
.idea/compiler.xml generated Executable file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Gradle Imported" enabled="true">
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.26/8f8cf0372abf564913e9796623aac4c8ea44025a/lombok-1.18.26.jar" />
</processorPath>
<module name="FileManager.main" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel target="17" />
</component>
</project>

9
.idea/dataSources.local.xml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="dataSourceStorageLocal" created-in="IU-242.20224.387">
<data-source name="thisServer" uuid="381e0765-93f7-4a59-8c32-52ac4efbe2c9">
<database-info product="" version="" jdbc-version="" driver-name="" driver-version="" dbms="MYSQL" />
<schema-mapping />
</data-source>
</component>
</project>

12
.idea/dataSources.xml generated Executable file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="thisServer" uuid="381e0765-93f7-4a59-8c32-52ac4efbe2c9">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://127.0.0.1:3306/fs</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

10
.idea/dictionaries/wzp.xml generated Executable file
View File

@ -0,0 +1,10 @@
<component name="ProjectDictionaryState">
<dictionary name="wzp">
<words>
<w>curdate</w>
<w>executeable</w>
<w>executeble</w>
<w>ffprobe</w>
</words>
</dictionary>
</component>

16
.idea/gradle.xml generated Executable file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

12
.idea/inspectionProfiles/Project_Default.xml generated Executable file
View File

@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="customHeaders">
<set>
<option value="Set-Authorization" />
</set>
</option>
</inspection_tool>
</profile>
</component>

20
.idea/jarRepositories.xml generated Executable file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

8
.idea/misc.xml generated Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="temurin-17" project-jdk-type="JavaSDK" />
</project>

8
.idea/modules/FileManager.main.iml generated Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main">
<sourceFolder url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main" isTestSource="false" generated="true" />
</content>
</component>
</module>

10
.idea/mybatisx/templates.xml generated Executable file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="TemplatesSettings">
<option name="templateConfigs">
<TemplateContext>
<option name="projectPath" value="$PROJECT_DIR$" />
</TemplateContext>
</option>
</component>
</project>

124
.idea/uiDesigner.xml generated Executable file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Executable file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

495
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,495 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="b1988503-f417-4c69-ad49-94239747bbea" name="变更" comment="feat: adding get files">
<change afterPath="$PROJECT_DIR$/src/main/java/cn/wzpmc/filemanager/configurations/AuthorizationConfiguration.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/cn/wzpmc/filemanager/utils/JwtUtils.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/cn/wzpmc/filemanager/utils/JwtUtils.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/test/java/cn/wzpmc/filemanager/FileManagerApplicationTests.java" beforeDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="ExternalProjectsManager">
<system id="GRADLE">
<state>
<task path="$PROJECT_DIR$">
<activation />
</task>
<projects_view>
<tree_state>
<expand>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="FileManager" type="f1a62948:ProjectNode" />
</path>
</expand>
<select />
</tree_state>
</projects_view>
</state>
</system>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="TypeScript File" />
<option value="HTML File" />
<option value="Enum" />
<option value="Class" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="HighlightingSettingsPerFile">
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/io/File.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/net/InetAddress.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/text/DateFormat.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/util/Calendar.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/util/Date.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.base/java/util/regex/Pattern.java" root0="SKIP_INSPECTION" />
<setting file="jar://$PROJECT_DIR$/../../../../JAVA_HOME/17/lib/src.zip!/java.xml/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.26/f43db6c43d481ab766a496c86dc43c145e3c9df4/lombok-1.18.26-sources.jar!/lombok/extern/slf4j/XSlf4j.java" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/6.0.7/6ed548931d69aeabeab4c5cc515ad2a2648baa8e/spring-web-6.0.7-sources.jar!/org/springframework/web/multipart/MultipartFile.java" root0="SKIP_INSPECTION" />
</component>
<component name="HttpClientSelectedEnvironments">
<file url="jar://$APPLICATION_HOME_DIR$/plugins/restClient/lib/restClient.jar!/com/intellij/ws/rest/client/requests/collection/post-requests.http" environment="test" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 6
}]]></component>
<component name="ProjectId" id="2NXvr90GVwvap0wwjD4LmMgnTam" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
"DefaultHtmlFileTemplate": "HTML File",
"Gradle.FileManager [jar].executor": "Run",
"RequestMappingsPanelOrder0": "0",
"RequestMappingsPanelOrder1": "1",
"RequestMappingsPanelWidth0": "75",
"RequestMappingsPanelWidth1": "75",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"WebServerToolWindowFactoryState": "false",
"git-widget-placeholder": "main",
"jdk.selected.JAVA_MODULE": "temurin-20",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "/server/home/wzp/Project/FileManager/src/main/resources/cn/wzpmc/filemanager/mapper",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"project.structure.last.edited": "SDKs",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "settings.typescriptcompiler",
"spring.configuration.checksum": "cb229e6877988f6160a29925ef6d914d",
"ts.external.directory.path": "/main/share/Projects/FileManager/FileManager/node_modules/typescript/lib",
"vue.rearranger.settings.migration": "true",
"远程 JVM 调试.未命名.executor": "Debug"
},
"keyToStringList": {
"DatabaseDriversLRU": [
"mysql"
]
}
}]]></component>
<component name="RdControllerToolWindowsLayoutState" isNewUi="true">
<layout>
<window_info id="Space Code Reviews" />
<window_info id="Bookmarks" side_tool="true" />
<window_info id="Commit_Guest" show_stripe_button="false" />
<window_info id="Pull Requests" />
<window_info id="Learn" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.18671875" />
<window_info id="Commit" order="1" weight="0.25" />
<window_info id="Structure" order="2" weight="0.17161459" />
<window_info anchor="bottom" id="Database Changes" weight="0.32994187" />
<window_info anchor="bottom" id="TypeScript" />
<window_info anchor="bottom" id="Profiler" />
<window_info anchor="bottom" id="Java Enterprise" weight="0.31831396" />
<window_info anchor="bottom" id="File Transfer" />
<window_info anchor="bottom" id="Find" show_stripe_button="false" weight="0.32994187" />
<window_info anchor="bottom" id="Dependency Checker" />
<window_info anchor="bottom" id="Version Control" order="0" />
<window_info anchor="bottom" id="Problems View" order="1" weight="0.30184108" />
<window_info anchor="bottom" id="Terminal" order="2" weight="0.31831396" />
<window_info anchor="bottom" id="Services" order="3" weight="0.44718993" />
<window_info anchor="bottom" id="Build" order="4" weight="0.31831396" />
<window_info active="true" anchor="bottom" id="Run" order="5" visible="true" weight="0.44718993" />
<window_info anchor="bottom" id="Spring" order="6" show_stripe_button="false" />
<window_info anchor="right" id="Endpoints" />
<window_info anchor="right" id="Beans" />
<window_info anchor="right" id="Meet New UI" show_stripe_button="false" side_tool="true" />
<window_info anchor="right" content_ui="combo" id="Notifications" order="0" weight="0.25" />
<window_info anchor="right" id="Database" order="1" weight="0.32994792" />
<window_info active="true" anchor="right" id="Gradle" order="2" visible="true" weight="0.32994792" />
</layout>
</component>
<component name="ReactorSettings">
<option name="notificationShown" value="true" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src/main/resources/cn/wzpmc/filemanager/mapper" />
<recent name="C:\Users\33572\Documents\Projects\IdeaProjects\FileManager" />
<recent name="C:\Users\33572\Documents\Projects\IdeaProjects\FileManager\FileManager\src\assets" />
<recent name="C:\Users\33572\Documents\Projects\IdeaProjects\FileManager\gradle\wrapper\dist" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\33572\Documents\Projects\IdeaProjects\FileManager\FileManager\public" />
</key>
</component>
<component name="RunDashboard">
<option name="configurationTypes">
<set>
<option value="SpringBootApplicationConfigurationType" />
<option value="js.build_tools.npm" />
</set>
</option>
</component>
<component name="RunManager" selected="Gradle.FileManager [jar]">
<configuration name="CheckTest" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":FFMpegJ:test" />
<option value="--tests" />
<option value="&quot;CheckTest&quot;" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>true</RunAsTest>
<method v="2" />
</configuration>
<configuration name="CheckTest.onTest" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":FFMpegJ:test" />
<option value="--tests" />
<option value="&quot;CheckTest.onTest&quot;" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>true</RunAsTest>
<method v="2" />
</configuration>
<configuration name="FileManager [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration name="FileManager [clean]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration name="FileManager [jar]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
<configuration default="true" type="JetRunConfigurationType">
<module name="FileManager.FFMpegJ.main" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="KotlinStandaloneScriptRunConfigurationType">
<module name="FileManager.FFMpegJ.main" />
<option name="filePath" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="未命名" type="Remote" nameIsGenerated="true">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="true" />
<option name="SHMEM_ADDRESS" />
<option name="HOST" value="192.168.1.4" />
<option name="PORT" value="5005" />
<option name="AUTO_RESTART" value="false" />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="5005" />
<option name="LOCAL" value="false" />
</RunnerSettings>
<method v="2" />
</configuration>
<configuration name="FileManagerApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
<module name="FileManager.main" />
<option name="SPRING_BOOT_MAIN_CLASS" value="cn.wzpmc.filemanager.FileManagerApplication" />
<option name="WORKING_DIRECTORY" value="file://run" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="dev" type="js.build_tools.npm" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/FileManager/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<package-manager value="yarn" />
<envs />
<method v="2" />
</configuration>
<list>
<item itemvalue="Gradle.FileManager [build]" />
<item itemvalue="Gradle.FileManager [jar]" />
<item itemvalue="Gradle.FileManager [clean]" />
<item itemvalue="Gradle.CheckTest" />
<item itemvalue="Gradle.CheckTest.onTest" />
<item itemvalue="npm.dev" />
<item itemvalue="Spring Boot.FileManagerApplication" />
<item itemvalue="远程 JVM 调试.未命名" />
</list>
<recent_temporary>
<list>
<item itemvalue="Gradle.FileManager [jar]" />
<item itemvalue="Gradle.FileManager [build]" />
<item itemvalue="Gradle.FileManager [clean]" />
<item itemvalue="Gradle.CheckTest.onTest" />
<item itemvalue="Gradle.CheckTest" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-jdk-9823dce3aa75-b114ca120d71-intellij.indexing.shared.core-IU-242.20224.387" />
<option value="bundled-js-predefined-d6986cc7102b-410509235cf1-JavaScript-IU-242.20224.387" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="b1988503-f417-4c69-ad49-94239747bbea" name="变更" comment="" />
<created>1679823462650</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1679823462650</updated>
<workItem from="1679823464586" duration="15521000" />
<workItem from="1679926037934" duration="8529000" />
<workItem from="1680013560331" duration="13244000" />
<workItem from="1680181608649" duration="10293000" />
<workItem from="1680311765915" duration="844000" />
<workItem from="1680312925618" duration="127000" />
<workItem from="1680313057480" duration="7318000" />
<workItem from="1680366214077" duration="3739000" />
<workItem from="1680606882950" duration="186000" />
<workItem from="1680607098537" duration="1225000" />
<workItem from="1680608338157" duration="989000" />
<workItem from="1680617042034" duration="518000" />
<workItem from="1680617646473" duration="135000" />
<workItem from="1680617789708" duration="207000" />
<workItem from="1680618003149" duration="219000" />
<workItem from="1680932900587" duration="28000" />
<workItem from="1681528254816" duration="55000" />
<workItem from="1681825747684" duration="2853000" />
<workItem from="1682258664381" duration="2743000" />
<workItem from="1682426315842" duration="7659000" />
<workItem from="1700232967665" duration="24000" />
<workItem from="1700232997037" duration="269000" />
<workItem from="1700233283121" duration="31000" />
<workItem from="1700233318805" duration="71000" />
<workItem from="1700233408562" duration="2759000" />
<workItem from="1700279208154" duration="6800000" />
<workItem from="1700305721886" duration="12355000" />
<workItem from="1700363852821" duration="17000" />
<workItem from="1700363878019" duration="929000" />
<workItem from="1700364822674" duration="7194000" />
<workItem from="1700379313976" duration="1910000" />
<workItem from="1700389972625" duration="17164000" />
<workItem from="1700991510202" duration="6016000" />
<workItem from="1701076119382" duration="3149000" />
<workItem from="1701517913965" duration="3782000" />
<workItem from="1701593245155" duration="8881000" />
<workItem from="1701666627683" duration="1315000" />
<workItem from="1701683274777" duration="1203000" />
<workItem from="1702046322259" duration="5022000" />
<workItem from="1702059853668" duration="24000" />
<workItem from="1724077806482" duration="5191000" />
</task>
<task id="LOCAL-00001" summary="feat: adding get files">
<created>1679928730544</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1679928730544</updated>
</task>
<task id="LOCAL-00002" summary="feat: adding get files">
<created>1681826752728</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1681826752728</updated>
</task>
<task id="LOCAL-00003" summary="feat: adding get files">
<created>1681826809345</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1681826809345</updated>
</task>
<option name="localTasksCounter" value="4" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="origin/main" />
</list>
</value>
</entry>
</map>
</option>
</State>
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="feat: adding get files" />
<option name="LAST_COMMIT_MESSAGE" value="feat: adding get files" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<breakpoint enabled="true" type="java-exception">
<properties class="java.io.EOFException" package="java.io" />
<option name="timeStamp" value="2" />
</breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/6.0.7/43f8ac9c46c15d57fca00fc81ce1f2849f6cecb9/spring-web-6.0.7.jar!/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.class</url>
<line>34</line>
<option name="timeStamp" value="8" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-method">
<url>jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/6.0.7/43f8ac9c46c15d57fca00fc81ce1f2849f6cecb9/spring-web-6.0.7.jar!/org/springframework/web/method/support/HandlerMethodArgumentResolver.class</url>
<line>16</line>
<properties class="org.springframework.web.method.support.HandlerMethodArgumentResolver" method="resolveArgument">
<option name="EMULATED" value="true" />
<option name="WATCH_EXIT" value="false" />
</properties>
<option name="timeStamp" value="7" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
<component name="XSLT-Support.FileAssociations.UIState">
<expand />
<select />
</component>
</project>

24
FileManager/.gitignore vendored Executable file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
FileManager/.vscode/extensions.json vendored Executable file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

18
FileManager/README.md Executable file
View File

@ -0,0 +1,18 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support For `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.

8
FileManager/auto-imports.d.ts vendored Executable file
View File

@ -0,0 +1,8 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-auto-import
export {}
declare global {
}

29
FileManager/components.d.ts vendored Executable file
View File

@ -0,0 +1,29 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import('element-plus/es')['ElButton']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTree: typeof import('element-plus/es')['ElTree']
ElUpload: typeof import('element-plus/es')['ElUpload']
}
}

13
FileManager/index.html Executable file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/SiHCl3.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SiHCL3-文件分享站</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

3525
FileManager/package-lock.json generated Executable file

File diff suppressed because it is too large Load Diff

27
FileManager/package.json Executable file
View File

@ -0,0 +1,27 @@
{
"name": "filemanager",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@vueuse/core": "^9.13.0",
"axios": "^1.3.4",
"element-plus": "^2.3.1",
"ts-md5": "^1.3.1",
"vue": "^3.2.45"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.0.0",
"typescript": "^4.9.3",
"unplugin-auto-import": "^0.15.2",
"unplugin-icons": "^0.15.3",
"unplugin-vue-components": "^0.24.1",
"vite": "^4.1.0",
"vue-tsc": "^1.0.24"
}
}

BIN
FileManager/public/SiHCl3.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

374
FileManager/src/App.vue Executable file
View File

@ -0,0 +1,374 @@
<script setup lang="ts">
import {onMounted, ref} from "vue";
import {Search, UploadFilled, Moon, Sunny, UserFilled} from "@element-plus/icons-vue"
import {FileObject} from "./entities/FileObject";
import {FileDetailsInfo, genDetails} from './entities/FileDetailsInfo'
import {Awaitable, useDark, useToggle} from "@vueuse/core";
import {
baseUrl,
deleteFile,
getFileCount, getFileDetails,
getFiles,
login,
register,
searchFiles,
upload
} from "./requester/Requester";
import {ElMessage, UploadFile, UploadFiles, UploadRawFile, UploadRequestOptions} from "element-plus";
const searchContent = ref<string>("");
const searchPlaceHolder = ref<string>("请输入要搜索的内容");
const searchType = ref<"NAME" | "ID" | "MD5">("NAME");
const searchContentType = ref<string>("text");
const nowShowData = ref<Array<FileObject>>([]);
const isAdmin = ref<boolean>(false);
const isDark = useDark();
const toggleDark = useToggle(isDark);
const colorTheme = ref<boolean>(isDark.value);
const totalFileCount = ref<number>(0);
const nowPage = ref<number>(1);
const isSearching = ref<boolean>(false);
const isShowDialog = ref<boolean>(false);
const usernameInput = ref<string>("");
const passwordInput = ref<string>("");
const usernameShow = ref<string>("请登录!");
const isShowDetailsInfo = ref<boolean>(false);
const detailsFileName = ref<string>("");
const fileDetailsInfo = ref<FileDetailsInfo[]>([]);
const abortControllers = new Map<string, AbortController>();
const onSearchTypeChange = (now: string) => {
switch (now){
case "NAME":
searchPlaceHolder.value = "请输入要搜索的内容的名称";
searchContentType.value = "text";
break;
case "ID":
searchPlaceHolder.value = "请输入要搜索的文件的id";
searchContentType.value = "number";
break;
case "MD5":
searchPlaceHolder.value = "请输入要搜索的文件的md5";
searchContentType.value = "text";
break;
case "FORMAT":
searchPlaceHolder.value = "请输入要搜索的文件的类型";
searchContentType.value = "text";
break;
}
if (isSearching.value){
searchContent.value = "";
isSearching.value = false;
nowPage.value = 1;
handleChangePage();
}
}
const handleShowDetail = (id: number, fileName: string) => {
getFileDetails(id).then((response) => {
fileDetailsInfo.value = genDetails(id, response.data);
detailsFileName.value = fileName;
isShowDetailsInfo.value = true;
}).catch((_) => {
ElMessage.error("无法获取文件详细信息!")
})
}
const handleDownload = (id: number) => {
window.open(baseUrl + "/api/file?id=" + id);
}
const handleColorThemeChange = () => {
toggleDark();
}
const handleChangePage = () => {
if (!isSearching.value){
getFileCount().then((response) => {
totalFileCount.value = response.data;
getFiles(nowPage.value).then((response) => {
nowShowData.value = response.data;
}).catch((_) => {
ElMessage.error("无法获取文件数据,请刷新重试!");
});
}).catch((_) => {
ElMessage.error("无法获取文件总数,请刷新重试!")
});
}else{
searchFiles(searchContent.value, searchType.value, nowPage.value).then((response) => {
totalFileCount.value = response.data.count;
nowShowData.value = response.data.data;
}).catch((_) => {
ElMessage.error("无法获取文件数据,请刷新重试!");
});
}
}
const handleSearch = () => {
nowPage.value = 1;
isSearching.value = searchContent.value !== "";
handleChangePage();
}
const getUsername = () => {
const username = sessionStorage.getItem("username");
if (username){
if (username === "wzp"){
isAdmin.value = true;
}
return username;
}
return "请登录!";
}
const handleLogin = () => {
login(usernameInput.value, passwordInput.value).then((response) => {
if (response.data.data !== null){
ElMessage.success("登录成功!");
window.sessionStorage.setItem("username", usernameInput.value);
usernameShow.value = usernameInput.value;
isShowDialog.value = false;
}else{
ElMessage.error("登录失败,用户名或密码错误!");
}
});
}
const handleRegister = () => {
register(usernameInput.value, passwordInput.value).then((response) => {
if (response.data.data !== null){
ElMessage.success("注册成功!");
window.sessionStorage.setItem("username", usernameInput.value);
usernameShow.value = usernameInput.value;
isShowDialog.value = false;
}
});
}
const needLogin = () => {
return window.sessionStorage.getItem("token") == null;
}
const handleUpload = (options: UploadRequestOptions): XMLHttpRequest | Promise<unknown> => {
const abortController = new AbortController();
abortControllers.set(options.file.name, abortController);
let promise = upload(options, abortController);
promise.then((response) => {
options.onSuccess(response);
}).catch((error) => {
options.onError(error)
}).finally(() => {
abortControllers.delete(options.filename);
});
return promise;
}
const handleUploadRemove = (uploadFile: UploadFile, _: UploadFiles): Awaitable<boolean> => {
const name = uploadFile.raw?.name as string;
const controller = abortControllers.get(name);
if (controller){
controller.abort("user");
ElMessage.success("成功取消!")
return true;
}
return false;
}
const handleUploadSuccess = (__: any, uploadFile: UploadFile, _: UploadFiles): void => {
ElMessage.success("文件" + uploadFile.raw?.name + "上传成功!");
}
const handleBeforeUpload = (_: UploadRawFile): boolean => {
if (needLogin()){
ElMessage.error("未登录,无法上传!");
return false;
}
return true;
}
const handleDelete = (id: number) => {
deleteFile(id).then((response) => {
if (response.data) {
ElMessage.success("删除成功!");
}else{
ElMessage.error("删除失败!");
}
})
}
const handleTranscoding = (data: FileDetailsInfo) => {
console.log(data.fid);
}
onMounted(() => {
nowPage.value = 1;
handleChangePage();
usernameShow.value = getUsername();
})
</script>
<template>
<el-dialog v-if="needLogin()" v-model="isShowDialog" title="登录或注册" width="30%" draggable>
<el-input v-model="usernameInput" placeholder="请输入用户名">
<template #prepend>用户名</template>
</el-input>
<el-input style="margin-top: 10px" v-model="passwordInput" placeholder="请输入密码" show-password>
<template #prepend>密码</template>
</el-input>
<template #footer>
<el-button @click="isShowDialog = false;">取消</el-button>
<el-button type="warning" @click="handleLogin">登录</el-button>
<el-button type="danger" @click="handleRegister">注册</el-button>
</template>
</el-dialog>
<el-dialog
v-model="isShowDetailsInfo"
:title="detailsFileName"
width="30%"
align-center
>
<el-tree
:data="fileDetailsInfo"
node-key="id"
:expand-on-click-node="false"
>
<template #default="{ node, data }">
<span style="width: 90%">{{ node.label }}</span>
<el-button style="width: 10%; height: 100%;" type="primary" text @click="handleTranscoding(data)" v-if="node.label.startsWith('编码格式: ')">转码</el-button>
</template>
</el-tree>
<template #footer>
<span class="dialog-footer">
<el-button @click="isShowDetailsInfo = false">退出</el-button>
</span>
</template>
</el-dialog>
<el-container>
<el-header style="height: 1%; display: flex;flex-direction: row">
<div class="header left">
<el-switch
v-model="colorTheme"
class="ml-2"
style="--el-switch-on-color: var(--el-border-color-dark); --el-switch-off-color: var(--el-border-color-light)"
:active-icon="Moon"
:inactive-icon="Sunny"
@change="handleColorThemeChange"
/>
<div class="search-box">
<el-input
:type="searchContentType"
v-model="searchContent"
:placeholder="searchPlaceHolder">
<template #prepend>
<el-select v-model="searchType" placeholder="Select" style="width: 100px" @change="onSearchTypeChange">
<el-option label="名字" value="NAME" />
<el-option label="ID" value="ID" />
<el-option label="MD5" value="MD5" />
<el-option label="文件类型" value="FORMAT" />
</el-select>
</template>
<template #append>
<el-button :icon="Search" @click="handleSearch" />
</template>
</el-input>
</div>
</div>
<div class="header right" @click="isShowDialog = true;">
<el-avatar :icon="UserFilled" />
<div style="text-align: center; height: 100%; margin-left: 10px; margin-top: auto; margin-bottom: auto;" v-text="usernameShow"></div>
</div>
</el-header>
<el-main style="padding-top: 0;padding-bottom: 0;">
<div class="main-box">
<div class="search-table-box">
<div class="table-box">
<el-table :data="nowShowData" style="width: 100%">
<el-table-column fixed prop="id" label="ID" width="80" />
<el-table-column prop="fileName" label="文件名" width="600" />
<el-table-column prop="fileFormat" label="文件格式" width="180" />
<el-table-column prop="fileSize" label="文件大小" width="120" />
<el-table-column prop="uploader" label="上传者" width="120" />
<el-table-column fixed="right" label="操作" width="180">
<template #default="scope">
<el-button link type="primary" size="small" @click="handleShowDetail(scope.row.id, scope.row.fileName);">详细信息</el-button>
<el-button link type="primary" size="small" @click="handleDownload(scope.row.id);">下载</el-button>
<el-button link type="primary" size="small" @click="handleDelete(scope.row.id);" v-if="isAdmin">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
hide-on-single-page
:page-size="20"
:pager-count="11"
layout="prev, pager, next"
:total="totalFileCount"
v-model:current-page="nowPage"
@currentChange="handleChangePage"
/>
</div>
</div>
<div class="uploader-preview-box">
<div class="uploader-box">
<el-upload
drag
:http-request="handleUpload"
:before-remove="handleUploadRemove"
:on-success="handleUploadSuccess"
:before-upload="handleBeforeUpload"
multiple>
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
<div class="el-upload__text">
把文件拖到这里或者 <em>点击这里</em> 上传
</div>
</el-upload>
</div>
<div class="preview-box">
</div>
</div>
</div>
</el-main>
</el-container>
</template>
<style scoped>
.main-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
}
.search-table-box {
display: flex;
flex-direction: column;
width: 72%;
height: 100%;
}
.search-box {
width: 30%;
height: 10%;
margin-left: 10px;
}
.table-box {
margin-top: 10px;
height: 90%;
width: 100%;
}
.uploader-preview-box {
height: 100%;
width: 28%;
margin-left: 10px;
margin-top: 10px;
display: flex;
flex-direction: column;
}
.uploader-box {
width: 100%;
height: 30%;
}
.preview-box {
width: 100%;
height: 70%;
}
.header {
height: 100%;
display: flex;
}
.left {
width: 70%;
justify-content: start;
}
.right {
width: 30%;
justify-content: end;
}
.right:hover {
cursor: pointer;
}
</style>

View File

@ -0,0 +1,21 @@
export interface FileDetailsInfo {
id: number;
fid: number;
label: string;
children: FileDetailsInfo[]
}
export const genDetails = (fid: number, data: any, id: number = 0): FileDetailsInfo[] => {
const result: FileDetailsInfo[] = [];
for (let key in data){
if (typeof data[key] === "string"){
const show = `${key}: ${data[key]}`;
result.push({id: id, label: show, children: [], fid: fid});
}else{
const init = genDetails(fid, data[key], id + 1);
result.push({id: id, label: key, children: init, fid: fid});
id += init.length;
}
id ++;
}
return result;
}

View File

@ -0,0 +1,9 @@
export interface FileObject {
id: number;
fileName: string;
fileSize: string;
fileFormat: string;
md5: string;
uploader: string;
uploadTime: string;
}

6
FileManager/src/main.ts Executable file
View File

@ -0,0 +1,6 @@
import { createApp } from 'vue'
import 'element-plus/es/components/message/style/css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import App from './App.vue'
const app = createApp(App)
app.mount("#app")

View File

@ -0,0 +1,90 @@
import axios from "axios";
import {Md5} from "ts-md5";
import {UploadRequestOptions} from "element-plus";
import {UploadProgressEvent} from "element-plus/es/components/upload/src/upload";
export const baseUrl = "http://localhost:8080";
const instance = axios.create({
baseURL: baseUrl,
timeout: 2000,
headers: {
"Content-Type": "application/json"
}
});
instance.interceptors.request.use(
(config) => {
const token = window.sessionStorage.getItem("token");
if (token){
config.headers.authorization = token;
}
return config;
}
)
instance.interceptors.response.use(
(config) => {
if (config.headers.authorization){
window.sessionStorage.setItem("token", config.headers.authorization);
}
return config;
}
)
export const getFileCount = () => {
return instance.get("/api/file/count")
}
export const getFiles = (page: number) => {
return instance.get("/api/file/get", {
params: {
page: page
}
})
}
export const searchFiles = (keywords: string, type: "NAME" | "ID" | "MD5", page: number = 1) => {
return instance.get("/api/file/search", {
params: {
page: page,
keywords: keywords,
type: type
}
})
}
export const login = (username: string, password: string) => {
const md5: Md5 = new Md5()
md5.appendAsciiStr(password)
const passwordMd5 = md5.end()
return instance.post("/api/user/login", {
username: username,
password: passwordMd5
})
}
export const register = (username: string, password: string) => {
const md5: Md5 = new Md5()
md5.appendAsciiStr(password)
const passwordMd5 = md5.end()
return instance.post("/api/user/register", {
username: username,
password: passwordMd5
})
}
export const upload = (options: UploadRequestOptions, controller: AbortController) => {
const param = new FormData();
param.append("file", options.file);
return instance.post("/api/file/upload", param, {
headers: {
"Content-Type": "multipart/form-data"
},
timeout: 0,
onUploadProgress: (evt) => {
const progressEvent: ProgressEvent = evt.event as ProgressEvent;
const uploadEvent: UploadProgressEvent = progressEvent as UploadProgressEvent;
uploadEvent.percent = (evt.progress as number) * 100;
options.onProgress(uploadEvent);
},
signal: controller.signal
})
}
export const deleteFile = (fileId: number) => {
return instance.post("/api/file/remove", {id: fileId})
}
export const getFileDetails = (fileId: number) => {
return instance.get("/api/file/details", {params: {"id": fileId}});
}

1
FileManager/src/vite-env.d.ts vendored Executable file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

18
FileManager/tsconfig.json Executable file
View File

@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

9
FileManager/tsconfig.node.json Executable file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

37
FileManager/vite.config.ts Executable file
View File

@ -0,0 +1,37 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import {ElementPlusResolver} from "unplugin-vue-components/resolvers";
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import IconResolver from 'unplugin-icons/dist/resolver'
import Icons from 'unplugin-icons/dist/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [
ElementPlusResolver(),
IconResolver({
prefix: "Icon"
})
],
}),
Components({
resolvers: [
IconResolver({
enabledCollections: ['ep']
}),
ElementPlusResolver()
],
}),
Icons({
autoInstall: true
})
],
server: {
host: "0.0.0.0",
port: 5173
}
})

83
HELP.md Executable file
View File

@ -0,0 +1,83 @@
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Gradle documentation](https://docs.gradle.org)
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.0.5/gradle-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.0.5/gradle-plugin/reference/html/#build-image)
* [GraalVM Native Image Support](https://docs.spring.io/spring-boot/docs/3.0.5/reference/html/native-image.html#native-image)
* [Spring Web](https://docs.spring.io/spring-boot/docs/3.0.5/reference/htmlsingle/#web)
* [MyBatis Framework](https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/)
* [JDBC API](https://docs.spring.io/spring-boot/docs/3.0.5/reference/htmlsingle/#data.sql)
### Guides
The following guides illustrate how to use some features concretely:
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/)
* [MyBatis Quick Start](https://github.com/mybatis/spring-boot-starter/wiki/Quick-Start)
* [Accessing Relational Data using JDBC with Spring](https://spring.io/guides/gs/relational-data-access/)
* [Managing Transactions](https://spring.io/guides/gs/managing-transactions/)
### Additional Links
These additional references should also help you:
* [Gradle Build Scans insights for your project's build](https://scans.gradle.com#gradle)
* [Configure AOT settings in Build Plugin](https://docs.spring.io/spring-boot/docs/3.0.5/gradle-plugin/reference/htmlsingle/#aot)
## GraalVM Native Support
This project has been configured to let you generate either a lightweight container or a native executable.
It is also possible to run your tests in a native image.
### Lightweight Container with Cloud Native Buildpacks
If you're already familiar with Spring Boot container images support, this is the easiest way to get started.
Docker should be installed and configured on your machine prior to creating the image.
To create the image, run the following goal:
```
$ ./gradlew bootBuildImage
```
Then, you can run the app like any other container:
```
$ docker run --rm -p 8080:8080 FileManager:0.0.1-SNAPSHOT
```
### Executable with Native Build Tools
Use this option if you want to explore more options such as running your tests in a native image.
The GraalVM `native-image` compiler should be installed and configured on your machine.
NOTE: GraalVM 22.3+ is required.
To create the executable, run the following goal:
```
$ ./gradlew nativeCompile
```
Then, you can run the app as follows:
```
$ build/native/nativeCompile/FileManager
```
You can also run your existing tests suite in a native image.
This is an efficient way to validate the compatibility of your application.
To run your existing tests in a native image, run the following goal:
```
$ ./gradlew nativeTest
```

86
LICENSE Normal file → Executable file
View File

@ -1,21 +1,73 @@
MIT License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2024 wzp
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
1. Definitions.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

7
README.md Normal file → Executable file
View File

@ -1,4 +1,3 @@
# File Manager
### A self-hosted file share and management system
___
## How to Use
# FileManager
My FileManager System

103
build.gradle.kts Normal file → Executable file
View File

@ -1,89 +1,46 @@
import java.net.URI
plugins {
java
id("org.springframework.boot") version "3.3.4"
id("io.spring.dependency-management") version "1.1.6"
id("org.graalvm.buildtools.native") version "0.10.3"
id("org.asciidoctor.jvm.convert") version "3.3.2"
java
id("org.springframework.boot") version "3.0.5"
id("io.spring.dependency-management") version "1.1.0"
id("org.graalvm.buildtools.native") version "0.9.20"
}
group = "cn.wzpmc"
group = "cn.wzpmc.filemanager"
version = "0.0.1-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
java.sourceCompatibility = JavaVersion.VERSION_17
configurations {
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
compileOnly {
extendsFrom(configurations.annotationProcessor.get())
}
}
repositories {
mavenCentral()
maven { url = URI("https://oss.sonatype.org/content/repositories/snapshots") }
mavenCentral()
}
extra["snippetsDir"] = file("build/generated-snippets")
extra["springShellVersion"] = "3.3.3"
dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-redis")
implementation("org.springframework.boot:spring-boot-starter-web"){
// remove jackson
exclude("org.springframework.book", "spring-boot-starter-json")
}
implementation("org.springframework.shell:spring-shell-starter")
// https://mvnrepository.com/artifact/com.mybatis-flex/mybatis-flex-spring-boot3-starter
implementation("com.mybatis-flex:mybatis-flex-spring-boot3-starter:1.9.7")
annotationProcessor("com.mybatis-flex:mybatis-flex-processor:1.9.7")
compileOnly("org.mybatis.spring.native:mybatis-spring-native-extensions:0.1.0-SNAPSHOT")
compileOnly("org.mybatis.spring.native:mybatis-spring-native-core:0.1.0-SNAPSHOT")
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
implementation("com.alibaba.fastjson2:fastjson2:2.0.46")
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension
implementation("com.alibaba.fastjson2:fastjson2-extension:2.0.46")
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension-spring6
implementation("com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.46")
// https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter
implementation("com.alibaba:druid-spring-boot-starter:1.2.23")
// https://mvnrepository.com/artifact/com.auth0/java-jwt
implementation("com.auth0:java-jwt:4.4.0")
// https://mvnrepository.com/artifact/commons-codec/commons-codec
implementation("commons-codec:commons-codec:1.17.1")
// https://mvnrepository.com/artifact/org.apache.tika/tika-core
implementation("org.apache.tika:tika-core:3.0.0-BETA2")
// https://mvnrepository.com/artifact/com.mysql/mysql-connector-j
implementation("com.mysql:mysql-connector-j:9.0.0")
compileOnly("org.projectlombok:lombok")
/*developmentOnly("org.springframework.boot:spring-boot-devtools")*/
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
testImplementation("org.springframework.shell:spring-shell-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
dependencyManagement {
imports {
mavenBom("org.springframework.shell:spring-shell-dependencies:${property("springShellVersion")}")
}
implementation("org.springframework.boot:spring-boot-starter-jdbc")
implementation("org.springframework.boot:spring-boot-starter-web"){
exclude("org.springframework.book", "spring-boot-starter-json")
}
implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.1")
// https://mvnrepository.com/artifact/com.auth0/java-jwt
implementation("com.auth0:java-jwt:4.3.0")
// https://mvnrepository.com/artifact/commons-codec/commons-codec
implementation("commons-codec:commons-codec:1.15")
implementation("org.springframework.boot:spring-boot-starter-data-redis")
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
implementation("com.alibaba.fastjson2:fastjson2:2.0.28")
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension
implementation("com.alibaba.fastjson2:fastjson2-extension:2.0.28")
implementation("com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.28")
compileOnly("org.projectlombok:lombok:1.18.26")
runtimeOnly("com.mysql:mysql-connector-j")
annotationProcessor("org.projectlombok:lombok:1.18.26")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.test {
outputs.dir(project.extra["snippetsDir"]!!)
}
tasks.asciidoctor {
inputs.dir(project.extra["snippetsDir"]!!)
dependsOn(tasks.test)
useJUnitPlatform()
}

4
gradle.properties Executable file
View File

@ -0,0 +1,4 @@
systemProp.http.proxyHost=192.168.5.6
systemProp.http.proxyPort=7890
systemProp.https.proxyHost=192.168.5.6
systemProp.https.proxyPort=7890

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file → Executable file

Binary file not shown.

4
gradle/wrapper/gradle-wrapper.properties vendored Normal file → Executable file
View File

@ -1,7 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

38
gradlew vendored Normal file → Executable file
View File

@ -15,8 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@ -57,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -82,12 +80,13 @@ do
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -134,29 +133,22 @@ location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -201,15 +193,11 @@ if "$cygwin" || "$msys" ; then
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \

23
gradlew.bat vendored Normal file → Executable file
View File

@ -13,8 +13,6 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@ -28,7 +26,6 @@ if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -45,11 +42,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@ -59,11 +56,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail

0
settings.gradle.kts Normal file → Executable file
View File

View File

@ -3,21 +3,11 @@ package cn.wzpmc.filemanager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.shell.command.annotation.EnableCommand;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = {"cn.wzpmc.filemanager.config"})
@MapperScan("cn.wzpmc.filemanager.mapper")
@EnableTransactionManagement
@EnableCommand
@EnableAsync
public class FileManagerApplication {
public static void main(String[] args) {
SpringApplication.run(FileManagerApplication.class, args);
}
}

View File

@ -1,11 +0,0 @@
package cn.wzpmc.filemanager.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Address {
}

View File

@ -1,15 +0,0 @@
package cn.wzpmc.filemanager.annotation;
import cn.wzpmc.filemanager.entities.user.enums.Auth;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorizationRequired {
Auth level() default Auth.user;
boolean force() default false;
}

View File

@ -1,20 +0,0 @@
package cn.wzpmc.filemanager.commands;
import cn.wzpmc.filemanager.entities.vo.UserVo;
import cn.wzpmc.filemanager.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
@ShellComponent
public class AuthorizationCommands {
private final UserService userService;
@Autowired
public AuthorizationCommands(UserService userService) {
this.userService = userService;
}
@ShellMethod("创建一个密钥")
public void key(){
this.userService.genInviteCode(UserVo.CONSOLE, "0.0.0.0");
}
}

View File

@ -1,13 +0,0 @@
package cn.wzpmc.filemanager.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.File;
@ConfigurationProperties(prefix = "wzp.filemanager.ffmpeg")
@Data
public class FFmpegConfiguration {
private File ffmpegPath;
private File ffprobePath;
}

View File

@ -1,16 +0,0 @@
package cn.wzpmc.filemanager.config;
import lombok.Data;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.File;
@ConfigurationProperties(prefix = "wzp.filemanager")
@Data
public class FileManagerProperties {
@Getter
private File savePath;
private String hmacKey = "RANDOM";
private FFmpegConfiguration ffmpeg;
}

View File

@ -1,21 +0,0 @@
package cn.wzpmc.filemanager.configuration;
import cn.wzpmc.filemanager.utils.AddressArgumentResolver;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
@RequiredArgsConstructor
public class AddressConfiguration implements WebMvcConfigurer {
private final AddressArgumentResolver addressArgumentResolver;
@Override
public void addArgumentResolvers(@NonNull List<HandlerMethodArgumentResolver> resolvers) {
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
resolvers.add(addressArgumentResolver);
}
}

View File

@ -1,34 +0,0 @@
package cn.wzpmc.filemanager.configuration;
import cn.wzpmc.filemanager.utils.AuthorizationArgumentResolver;
import cn.wzpmc.filemanager.utils.AuthorizationHandlerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class AuthorizationConfiguration implements WebMvcConfigurer {
private final AuthorizationArgumentResolver authorizationArgumentResolver;
private final AuthorizationHandlerInterceptor authorizationHandlerInterceptor;
@Autowired
public AuthorizationConfiguration(AuthorizationArgumentResolver authorizationArgumentResolver, AuthorizationHandlerInterceptor authorizationHandlerInterceptor) {
this.authorizationArgumentResolver = authorizationArgumentResolver;
this.authorizationHandlerInterceptor = authorizationHandlerInterceptor;
}
@Override
public void addArgumentResolvers(@NonNull List<HandlerMethodArgumentResolver> resolvers) {
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
resolvers.add(authorizationArgumentResolver);
}
@Override
public void addInterceptors(@NonNull InterceptorRegistry registry) {
WebMvcConfigurer.super.addInterceptors(registry);
registry.addInterceptor(authorizationHandlerInterceptor);
}
}

View File

@ -1,19 +0,0 @@
package cn.wzpmc.filemanager.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //允许所有路径进行CORS
// .maxAge(300 * 1000)
// .allowedOrigins("https://localhost:5173", "https://127.0.0.1:5173", "http://localhost:5173", "http://127.0.0.1:5173", "http://192.168.31.12:5173", "https://192.168.31.12:5173", "https://local.wzpmc.cn:5173")
.allowedHeaders("*")
.exposedHeaders("Add-Authorization")
.allowedMethods("*"); //允许所有请求方式
}
}

View File

@ -1,85 +0,0 @@
package cn.wzpmc.filemanager.configuration;
import cn.wzpmc.filemanager.config.FFmpegConfiguration;
import cn.wzpmc.filemanager.config.FileManagerProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.Objects;
@Component
@Slf4j
public class FileManagerConfiguration {
private final FileManagerProperties properties;
@Autowired
public FileManagerConfiguration(FileManagerProperties properties){
this.properties = properties;
}
public File getSavePath(){
File savePath = properties.getSavePath();
if (!savePath.isDirectory()){
if (!savePath.mkdirs()){
log.error("无法创建存储文件夹:{}", savePath);
return null;
}
}
return savePath;
}
private File searchFileInPath(String filename){
for (String path : (System.getProperty("user.dir") + ":" + System.getenv("PATH")).split(File.pathSeparator)) {
File file = new File(path);
if (file.isDirectory()) {
File[] possibleFiles = file.listFiles((fn) -> fn.getName().equalsIgnoreCase(filename));
if (possibleFiles == null){
continue;
}
if (possibleFiles.length != 0) {
return possibleFiles[0];
}
}
}
return null;
}
private File ffmpegExecuteableFile = null;
public File getFFMpegExecutebleFile(){
if (Objects.nonNull(ffmpegExecuteableFile)){
return ffmpegExecuteableFile;
}
FFmpegConfiguration ffmpeg = properties.getFfmpeg();
File ffmpegPath = ffmpeg.getFfmpegPath();
if (ffmpegPath == null){
ffmpegExecuteableFile = searchFileInPath("ffmpeg");
} else {
ffmpegExecuteableFile = ffmpegPath;
if (!ffmpegExecuteableFile.isFile()){
this.ffmpegExecuteableFile = null;
}
}
if (ffmpegExecuteableFile == null){
log.error("找不到FFmpeg可执行程序请尝试指定wzp.filemanager.ffmpeg.ffmpeg-path");
}
return ffmpegExecuteableFile;
}
private File ffprobeExecutebleFile = null;
public File getFFProbeExecutebleFile(){
if (Objects.nonNull(ffprobeExecutebleFile)) {
return this.ffprobeExecutebleFile;
}
FFmpegConfiguration ffmpeg = properties.getFfmpeg();
File ffprobePath = ffmpeg.getFfprobePath();
if (ffprobePath == null){
ffprobeExecutebleFile = searchFileInPath("ffprobe");
} else {
ffprobeExecutebleFile = ffprobePath;
if (!ffprobeExecutebleFile.isFile()){
this.ffprobeExecutebleFile = null;
}
}
if (ffprobeExecutebleFile == null){
log.error("找不到FFProbe可执行程序请尝试指定wzp.filemanager.ffmpeg.ffprobe-path");
}
return ffprobeExecutebleFile;
}
}

View File

@ -1,26 +0,0 @@
package cn.wzpmc.filemanager.configuration;
import cn.wzpmc.filemanager.entities.vo.FileVo;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
@Getter
public class RedisConfiguration {
private final RedisConnectionFactory redisConnectionFactory;
@Autowired
public RedisConfiguration(RedisConnectionFactory redisConnectionFactory) {
this.redisConnectionFactory = redisConnectionFactory;
}
@Bean
public RedisTemplate<String, FileVo> linkMapper() {
RedisTemplate<String, FileVo> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}

View File

@ -0,0 +1,70 @@
package cn.wzpmc.filemanager.configurations;
import cn.wzpmc.filemanager.entities.User;
import cn.wzpmc.filemanager.utils.JwtUtils;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.*;
@Configuration
@Component
public class AuthorizationConfiguration implements Filter {
private final JwtUtils jwtUtils;
@Autowired
public AuthorizationConfiguration(JwtUtils jwtUtils){
this.jwtUtils = jwtUtils;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof HttpServletRequest request) {
if (servletResponse instanceof HttpServletResponse response) {
String header = request.getHeader("Authorization");
if (header != null){
try {
this.jwtUtils.verifyToken(header);
} catch (TokenExpiredException e){
User decodeUser = this.jwtUtils.forceDecode(header);
if (decodeUser != null){
String token = this.jwtUtils.createToken(decodeUser);
CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(request);
requestWrapper.setAuthorization(token);
response.addHeader("Set-Authorization", token);
filterChain.doFilter(requestWrapper, response);
return;
}
} catch (JWTVerificationException ignored){}
}
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
private static final class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
@Setter(AccessLevel.PRIVATE)
private String authorization = null;
private CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public Enumeration<String> getHeaders(String name) {
if (name.equals("Authorization")){
return Collections.enumeration(Collections.singleton(authorization));
}
return super.getHeaders(name);
}
}
}

View File

@ -0,0 +1,19 @@
package cn.wzpmc.filemanager.configurations;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //**匹配的是我们所有后台的路径代表后台共享了什么资源
.maxAge(300 * 1000)
.allowedOrigins("https://localhost:5173", "https://127.0.0.1:5173", "http://localhost:5173", "http://127.0.0.1:5173", "http://192.168.31.12:5173", "https://192.168.31.12:5173")
.allowedHeaders("*")
.exposedHeaders("Set-Authorization")
.allowedMethods("*"); //允许的前台的请求方式
}
}

View File

@ -1,16 +1,14 @@
package cn.wzpmc.filemanager.configuration;
package cn.wzpmc.filemanager.configurations;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ -21,15 +19,12 @@ public class FastJsonConfiguration implements WebMvcConfigurer {
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastJsonConfig.setCharset(StandardCharsets.UTF_8);
JSONWriter.Feature[] writerFeatures = {JSONWriter.Feature.IgnoreNonFieldGetter, JSONWriter.Feature.PrettyFormat};
JSONWriter.Feature[] writerFeatures = {JSONWriter.Feature.MapSortField, JSONWriter.Feature.IgnoreNonFieldGetter, JSONWriter.Feature.PrettyFormat};
if (!debug) {
writerFeatures = new JSONWriter.Feature[]{JSONWriter.Feature.IgnoreNonFieldGetter};
writerFeatures = new JSONWriter.Feature[]{JSONWriter.Feature.MapSortField, JSONWriter.Feature.IgnoreNonFieldGetter};
}
fastJsonConfig.setWriterFeatures(writerFeatures);
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
ArrayList<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON);
converter.setSupportedMediaTypes(mediaTypes);
converter.setFastJsonConfig(fastJsonConfig);
converters.add(0, converter);
}

View File

@ -0,0 +1,97 @@
package cn.wzpmc.filemanager.configurations;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.Objects;
@Component
@Slf4j
public class FileManagerConfiguration {
@Value("${wzp.filemanager.save-path}")
private File savePath;
public File getSavePath(){
if (!savePath.isDirectory()){
if (!savePath.mkdirs()){
log.error("无法创建存储文件夹:{}", savePath);
return null;
}
}
return savePath;
}
private File searchFileInPath(String filename){
for (String path : (System.getProperty("user.dir") + ":" + System.getenv("PATH")).split(File.pathSeparator)) {
File file = new File(path);
if (file.isDirectory()) {
File[] possibleFiles = file.listFiles((fn) -> fn.getName().equalsIgnoreCase(filename));
if (possibleFiles == null){
continue;
}
if (possibleFiles.length != 0) {
return possibleFiles[0];
}
}
}
return null;
}
@Value("${wzp.filemanager.ffmpeg-path}")
private String ffmpegPath;
private File ffmpegExecuteableFile = null;
public File getFFMpegExecutebleFile(){
if (ffmpegPath == null){
return null;
}
if (Objects.isNull(ffmpegExecuteableFile)){
if ("AUTO".equalsIgnoreCase(ffmpegPath)){
ffmpegExecuteableFile = searchFileInPath("ffmpeg");
}else {
ffmpegExecuteableFile = new File(ffmpegPath);
if (!ffmpegExecuteableFile.isFile()){
this.ffmpegExecuteableFile = null;
}
}
}
if (ffmpegExecuteableFile == null){
log.error("找不到FFMpeg可执行程序请尝试指定wzp.filemanager.ffmpeg-path");
}
return ffmpegExecuteableFile;
}
@Value("${wzp.filemanager.ffprobe-path}")
private String ffprobePath;
private File ffprobeExecutebleFile = null;
public File getFFProbeExecutebleFile(){
if (ffprobePath == null){
return null;
}
if (Objects.isNull(ffprobeExecutebleFile)){
if ("AUTO".equalsIgnoreCase(ffprobePath)){
ffprobeExecutebleFile = searchFileInPath("ffprobe");
} else {
ffprobeExecutebleFile = new File(ffprobePath);
if (!ffprobeExecutebleFile.isFile()){
this.ffprobeExecutebleFile = null;
}
}
}
if (ffprobeExecutebleFile == null){
log.error("找不到FFProbe可执行程序请尝试指定wzp.filemanager.ffprobe-path");
}
return ffprobeExecutebleFile;
}
@Value("${wzp.filemanager.tmp-path}")
private File tmpPath;
public File getTmpPath(){
if (tmpPath == null){
return null;
}
if (!tmpPath.isDirectory()){
if (tmpPath.mkdirs()) {
log.error("无法创建缓存目录:{}", tmpPath);
return null;
}
}
return tmpPath;
}
}

View File

@ -0,0 +1,38 @@
package cn.wzpmc.filemanager.configurations;
import cn.wzpmc.filemanager.service.AccessService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer, HandlerInterceptor {
private final AccessService accessService;
@Autowired
public StaticResourceConfiguration(AccessService accessService){
this.accessService = accessService;
}
@Override
public void addResourceHandlers(@NonNull ResourceHandlerRegistry registry) {
registry.addResourceHandler("/*")
.addResourceLocations("./static/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this)
.addPathPatterns("/index.html");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
this.accessService.addAccessCounter();
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}

View File

@ -0,0 +1,26 @@
package cn.wzpmc.filemanager.controller;
import cn.wzpmc.filemanager.entities.AccessInformation;
import cn.wzpmc.filemanager.service.AccessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/access")
public class AccessController {
private final AccessService service;
@Autowired
public AccessController(AccessService service){
this.service = service;
}
@GetMapping("/get")
public List<AccessInformation> getAccessInformation(@RequestParam("count") int count){
return this.service.getAccessInformation(count);
}
@GetMapping("/getAll")
public AccessInformation getAllAccessInformation(){
return this.service.getAllAccessInformation();
}
}

View File

@ -0,0 +1,20 @@
package cn.wzpmc.filemanager.controller;
import cn.wzpmc.filemanager.entities.Result;
import cn.wzpmc.filemanager.service.CodecService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/codec")
public class CodecController {
private final CodecService service;
@Autowired
public CodecController(CodecService service){
this.service = service;
}
@GetMapping("/test")
public Result<String> getFileType(@RequestParam("id") int id){
return this.service.getFileType(id);
}
}

View File

@ -1,192 +1,53 @@
package cn.wzpmc.filemanager.controller;
import cn.wzpmc.filemanager.annotation.Address;
import cn.wzpmc.filemanager.annotation.AuthorizationRequired;
import cn.wzpmc.filemanager.entities.PageResult;
import cn.wzpmc.filemanager.entities.FileObject;
import cn.wzpmc.filemanager.entities.Page;
import cn.wzpmc.filemanager.entities.Result;
import cn.wzpmc.filemanager.entities.chunk.CheckChunkResult;
import cn.wzpmc.filemanager.entities.chunk.SaveChunksRequest;
import cn.wzpmc.filemanager.entities.files.FolderCreateRequest;
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
import cn.wzpmc.filemanager.entities.files.enums.FileType;
import cn.wzpmc.filemanager.entities.files.enums.SortField;
import cn.wzpmc.filemanager.entities.vo.FileVo;
import cn.wzpmc.filemanager.entities.vo.FolderVo;
import cn.wzpmc.filemanager.entities.vo.UserVo;
import cn.wzpmc.filemanager.entities.vo.FileObjectVo;
import cn.wzpmc.filemanager.enums.SearchType;
import cn.wzpmc.filemanager.service.FileService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.util.Date;
import java.util.List;
import java.io.IOException;
/**
* 文件操作相关接口
*/
@RestController
@RequestMapping("/api/file")
@RequiredArgsConstructor
public class FileController {
private final FileService fileService;
/**
* 上传一个文件
* @param file Multipart格式的文件对象
* @return 文件详情
*/
@PutMapping("/upload")
public Result<FileVo> simpleUpload(MultipartHttpServletRequest file, @AuthorizationRequired UserVo user, @Address String address) {
return fileService.simpleUpload(file, user, address);
private final FileService service;
@Autowired
public FileController(FileService service){
this.service = service;
}
/**
* 分页获取文件
* @param page 要获取第几页的文件
* @param num 每一页的文件数量
* @param folder 要获取的文件所在的文件夹
* @param sort 文件的排序方式
* @param reverse 是否反向排序
* @return 分页后的文件列表
*/
@GetMapping("/get")
public Result<PageResult<FullRawFileObject>> getFilePager(@RequestParam long page, @RequestParam int num, @RequestParam long folder, @RequestParam(defaultValue = "TIME") SortField sort, @RequestParam(defaultValue = "false") boolean reverse) {
return fileService.getFilePager(page, num, folder, sort, reverse);
@GetMapping("/checkUpload")
public Result<Boolean> checkUpload(@RequestParam("filename") String filename){
return service.checkUpload(filename);
}
/**
* 创建一个文件夹
* @param request 创建文件夹的相关参数
* @return 创建的文件夹详情
*/
@PostMapping("/mkdir")
public Result<FolderVo> mkdir(@RequestBody FolderCreateRequest request, @AuthorizationRequired UserVo user, @Address String address) {
return fileService.mkdir(request, user, address);
@PostMapping("/upload")
public Result<FileObjectVo> uploadFile(@RequestBody MultipartFile file, @RequestHeader("Authorization") String authorization){
return service.uploadFile(file, authorization);
}
/**
* 获取一个文件的简略信息
* @param id 文件ID
* @return 文件简略信息
*/
@GetMapping("/get/file")
public Result<FullRawFileObject> getFile(@RequestParam long id) {
return fileService.getFile(id);
}
/**
* 获取一个文件夹的简略信息
* @param id 文件夹ID
* @return 文件夹简略信息
*/
@GetMapping("/get/folder")
public Result<FullRawFileObject> getFolder(@RequestParam long id) {
return fileService.getFolder(id);
}
/**
* 获取文件详细信息
* @param id 文件ID
* @return 文件详细信息
*/
@GetMapping("/detail/file")
public Result<FileVo> getFileDetail(@RequestParam long id) {
return fileService.getFileDetail(id);
}
/**
* 删除一个文件/文件夹
* @param id 文件/文件夹ID
* @param type 目标为文件/文件夹
* @return 是否删除成功
*/
@DeleteMapping("/rm")
public Result<Void> delete(@RequestParam long id, @RequestParam FileType type, @AuthorizationRequired UserVo user, @Address String address) {
return fileService.delete(id, type, user, address);
}
/**
* 获取文件下载链接
* @param id 文件ID
* @return 文件下载链接ID
*/
@GetMapping("/link")
public Result<String> getFileLink(@RequestParam long id, @Address String address, HttpServletRequest request) {
return fileService.getFileLink(id, address, request);
public Result<String> generatorDownloadLink(@RequestParam("id") int id, HttpServletRequest request){
return service.generatorDownloadLink(id, request);
}
/**
* 通过下载文件ID下载文件
* @param id 下载ID
* @see #getFileLink(long, String, HttpServletRequest)
*/
@GetMapping("/download/{id}")
public void downloadFile(@PathVariable String id, @RequestHeader(value = "Range", defaultValue = "null") String range, HttpServletResponse response) {
fileService.downloadFile(id, range, response);
@GetMapping("/download/{fileLink}")
public void downloadFile(@PathVariable("fileLink") String link, HttpServletResponse response) throws IOException {
service.downloadFile(link, response);
}
/**
* 分享文件
* @deprecated
*/
@GetMapping("/share")
@Deprecated
public Result<String> shareFile(@RequestParam Long id, @RequestParam(defaultValue = "9999-12-31") Date lastCouldDownloadTime, @RequestParam(defaultValue = "-1") int maxDownloadCount) {
return fileService.shareFile(id, lastCouldDownloadTime, maxDownloadCount);
@GetMapping("/getAll")
public Result<Page<FileObjectVo>> getAllFile(@RequestParam("page") int page, @RequestParam("num") int num){
return service.getAllFile(page, num);
}
/**
* 通过路径解析文件信息
* @param path 需要解析的文件路径
* @return 文件粗略信息
*/
@GetMapping("/path/resolve")
public Result<FullRawFileObject> resolveFileDetail(@RequestParam String path) {
return fileService.resolveFileDetail(path);
@PostMapping("/remove")
public Result<Boolean> removeFile(@RequestBody FileObject fileObject, @RequestHeader("Authorization") String authorization) {
return service.removeFile(fileObject.getId(), authorization);
}
/**
* 通过文件ID获取文件路径
* @param id 文件ID
* @param type 目标文件为文件/文件夹
* @return 文件的路径
*/
@GetMapping("/path/{id}")
public Result<String> findFilePathById(@PathVariable("id") long id, @RequestParam(value = "type", defaultValue = "FILE") FileType type) {
return type.equals(FileType.FILE) ? fileService.findFilePathById(id) : fileService.findFolderPathById(id);
}
/**
* 获取需要上传的区块列表
* @param hash 文件分块后的所有hash值
* @return 需要上传的区块哈希和区块ID
*/
@PostMapping("/chunk/check")
public Result<List<CheckChunkResult>> checkChunkUploaded(@RequestBody List<String> hash) {
return fileService.checkChunkUploaded(hash);
}
/**
* 上传一个区块
* @param block 区块文件
* @return 上传的区块ID
*/
@PostMapping("/chunk/upload")
public Result<Long> uploadChunk(@RequestBody MultipartFile block) {
return fileService.uploadChunk(block);
}
/**
* 将区块保存为文件
* @param request 保存文件请求
* @return 保存后的文件
*/
@PutMapping("/chunk/save")
public Result<FileVo> saveFile(@RequestBody SaveChunksRequest request) {
return fileService.saveFile(request);
@GetMapping("/search")
public Result<Page<FileObjectVo>> searchFile(@RequestParam("page") int page, @RequestParam("num") int num, @RequestParam("type") SearchType type, @RequestParam("data") String data) {
return service.search(page, num, type, data);
}
}

View File

@ -1,16 +0,0 @@
package cn.wzpmc.filemanager.controller;
import cn.wzpmc.filemanager.entities.Result;
import cn.wzpmc.filemanager.exceptions.AuthorizationException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AuthorizationException.class)
public ResponseEntity<Result<Void>> handleAuthorizationException(AuthorizationException e) {
Result<Void> result = e.getResult();
return ResponseEntity.ok(result);
}
}

View File

@ -1,73 +1,32 @@
package cn.wzpmc.filemanager.controller;
import cn.wzpmc.filemanager.annotation.Address;
import cn.wzpmc.filemanager.annotation.AuthorizationRequired;
import cn.wzpmc.filemanager.entities.Result;
import cn.wzpmc.filemanager.entities.user.UserLoginRequest;
import cn.wzpmc.filemanager.entities.user.UserRegisterRequest;
import cn.wzpmc.filemanager.entities.user.enums.Auth;
import cn.wzpmc.filemanager.entities.vo.UserVo;
import cn.wzpmc.filemanager.entities.User;
import cn.wzpmc.filemanager.entities.vo.UserLoginVo;
import cn.wzpmc.filemanager.entities.vo.UserRegisterVo;
import cn.wzpmc.filemanager.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 用户相关接口
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/**
* 登录接口
* @param loginRequest 登录请求体
* @response {@link Result<UserVo>}
*/
private final UserService service;
@Autowired
public UserController(UserService service){
this.service = service;
}
@PostMapping("/login")
public void login(@RequestBody UserLoginRequest loginRequest, HttpServletResponse response, @Address String address) {
userService.login(loginRequest, response, address);
public Result<User> login(@RequestBody UserLoginVo loginVo, HttpServletResponse response){
return service.login(loginVo, response);
}
/**
* 注册接口
* @param registerRequest 注册请求体
* @response {@link Result<UserVo>}
*/
@PutMapping("/register")
public void register(@RequestBody UserRegisterRequest registerRequest, HttpServletResponse response, @Address String address) {
userService.register(registerRequest, response, address);
@PostMapping("/register")
public Result<User> register(@RequestBody UserRegisterVo registerVo, HttpServletResponse response){
return service.register(registerVo, response);
}
/**
* 管理员用户生成邀请码接口
* @return 邀请码
*/
@GetMapping("/invite")
public Result<String> invite(@AuthorizationRequired(level = Auth.admin) UserVo userVo, @Address String address) {
return userService.invite(userVo, address);
}
/**
* 获取用户信息接口
* @return 用户信息
*/
@GetMapping("/info")
public Result<UserVo> getUserInfo(@AuthorizationRequired UserVo user) {
return Result.success(user);
}
/**
* 获取指定用户信息接口
* @param id 用户ID
* @return 该ID的用户信息
*/
@GetMapping("/info/{id}")
public Result<UserVo> getUser(@PathVariable Long id) {
return userService.getUserInformation(id);
@GetMapping("/verifyCode")
public Result<String> generatorVerifyCode(@RequestHeader("Authorization") String authorization){
return service.generatorVerifyCode(authorization);
}
}

View File

@ -0,0 +1,16 @@
package cn.wzpmc.filemanager.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class AccessInformation {
private long totalDownload;
private long totalAccess;
private Date date;
}

View File

@ -0,0 +1,28 @@
package cn.wzpmc.filemanager.entities;
import lombok.Data;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Objects;
@Data
public class FileObject {
private int id;
private String name;
private String type;
private long size;
private String hash;
private int uploader;
private Date uploadTime;
private int downloadCount;
public String generatorFileName() {
StringBuilder stringBuilder = new StringBuilder(name);
if (Objects.nonNull(type)){
stringBuilder.append('.').append(type);
}
return URLEncoder.encode(stringBuilder.toString(), StandardCharsets.UTF_8);
}
}

View File

@ -0,0 +1,13 @@
package cn.wzpmc.filemanager.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.List;
@Data
@AllArgsConstructor
public class Page<T> {
private int total;
private List<T> data;
}

View File

@ -1,21 +0,0 @@
package cn.wzpmc.filemanager.entities;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.List;
@Data
@AllArgsConstructor
@JSONCompiled
public class PageResult<T> {
/**
* 总行数
*/
private long total;
/**
* 当前页数据
*/
private List<T> data;
}

142
src/main/java/cn/wzpmc/filemanager/entities/Result.java Normal file → Executable file
View File

@ -1,136 +1,66 @@
package cn.wzpmc.filemanager.entities;
import cn.wzpmc.filemanager.enums.HttpCodes;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@Data
@JSONCompiled
public class Result<T> {
/**
* 请求的响应码
*/
private int status;
/**
* 请求的响应信息
*/
private String msg;
/**
* 请求的响应数据
*/
private String message;
private T data;
/**
* 请求生成的时间戳
*/
private long timestamp;
protected Result() {
public Result() {
this.timestamp = System.currentTimeMillis();
}
protected Result(int status, String msg, T data) {
this();
this.status = status;
this.msg = msg;
this.data = data;
public static<T> Result<T> success(){
return success(null);
}
public static<T> Result<T> success(T data){
Result<T> rData = new Result<>();
rData.setStatus(HttpCodes.HTTP_CODES200.getCode());
rData.setMessage(HttpCodes.HTTP_CODES200.getMessage());
rData.setData(data);
return rData;
}
public static<T> Result<T> failed(HttpCodes httpCodes){
return failed(httpCodes, null);
}
public static<T> Result<T> failed(HttpCodes httpCodes, T data){
Result<T> rData = new Result<>();
rData.setStatus(httpCodes.getCode());
rData.setMessage(httpCodes.getMessage());
rData.setData(data);
return rData;
}
public static<T> Result<T> copyFailed(Result<?> original){
Result<T> rData = new Result<>();
rData.setStatus(original.getStatus());
rData.setMessage(original.getMessage());
rData.setTimestamp(original.getTimestamp());
return rData;
}
protected Result(HttpStatus status) {
this();
this.status = status.value();
this.msg = status.getReasonPhrase();
public static<T> Result<Page<T>> page(int total, List<T> data){
return Result.success(new Page<>(total, data));
}
protected Result(HttpStatus status, String msg) {
this(status);
this.msg = msg;
}
protected Result(HttpStatus status, T data) {
this(status);
this.data = data;
}
protected Result(HttpStatus status, String msg, T data) {
this(status, msg);
this.data = data;
}
public static <T> Result<T> success() {
return new Result<>(HttpStatus.OK);
}
public static <T> Result<T> success(String msg) {
return new Result<>(HttpStatus.OK, msg);
}
public static <T> Result<T> success(T data) {
return new Result<>(HttpStatus.OK, data);
}
public static <T> Result<T> success(String msg, T data) {
return new Result<>(HttpStatus.OK, msg, data);
}
public static <T> Result<T> failed() {
return new Result<>(HttpStatus.FORBIDDEN);
}
public static <T> Result<T> failed(String msg) {
return new Result<>(HttpStatus.FORBIDDEN, msg);
}
public static <T> Result<T> failed(HttpStatus status) {
return new Result<>(status);
}
public static <T> Result<T> failed(HttpStatus status, String msg) {
return new Result<>(status, msg);
}
public static <T> Result<T> create() {
return new Result<>();
}
public Result<T> status(int status) {
this.status = status;
return this;
}
public Result<T> status(HttpStatus status) {
this.status = status.value();
this.msg = status.getReasonPhrase();
return this;
}
public Result<T> msg(String msg) {
this.msg = msg;
return this;
}
public Result<T> data(T data) {
this.data = data;
return this;
}
public void writeToResponse(HttpServletResponse response) {
response.addHeader("Content-Type", "application/json; charset=utf-8");
try (ServletOutputStream outputStream = response.getOutputStream()) {
public void writeToResponse(HttpServletResponse response){
try(ServletOutputStream outputStream = response.getOutputStream()){
writeToOutputStream(outputStream);
} catch (IOException e) {
log.trace("写出到流失败,", e);
e.printStackTrace();
}
}
public void writeToOutputStream(OutputStream stream) throws IOException {
stream.write(JSON.toJSONString(this).getBytes(StandardCharsets.UTF_8));
}

View File

@ -0,0 +1,15 @@
package cn.wzpmc.filemanager.entities;
import cn.wzpmc.filemanager.entities.abs.PasswordObject;
import cn.wzpmc.filemanager.enums.Auth;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.codec.digest.DigestUtils;
@EqualsAndHashCode(callSuper = true)
@Data
public class User extends PasswordObject {
private int id;
private String name;
private Auth auth;
}

View File

@ -0,0 +1,19 @@
package cn.wzpmc.filemanager.entities.abs;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.codec.digest.DigestUtils;
@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class PasswordObject {
protected String password;
public void clearPassword(){
this.setPassword(null);
}
public void sha512Password(){
this.setPassword(DigestUtils.sha512Hex(this.getPassword()));
}
}

View File

@ -1,17 +0,0 @@
package cn.wzpmc.filemanager.entities.chunk;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class CheckChunkResult {
/**
* 区块哈希值
*/
private String hash;
/**
* 区块ID当区块存在时存在的区块ID
*/
private Long chunkId;
}

View File

@ -1,21 +0,0 @@
package cn.wzpmc.filemanager.entities.chunk;
import lombok.Data;
import java.util.List;
@Data
public class SaveChunksRequest {
/**
* 文件名
*/
private String filename;
/**
* 区块列表
*/
private List<Long> chunks;
/**
* 文件夹ID根目录为-1
*/
private Long folderId;
}

View File

@ -1,17 +0,0 @@
package cn.wzpmc.filemanager.entities.files;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import lombok.Data;
@Data
@JSONCompiled
public class FolderCreateRequest {
/**
* 父文件夹ID
*/
private long parent;
/**
* 文件名
*/
private String name;
}

View File

@ -1,25 +0,0 @@
package cn.wzpmc.filemanager.entities.files;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@Table("raw_file")
@Data
@AllArgsConstructor
@NoArgsConstructor
@JSONCompiled
public class FullRawFileObject extends RawFileObject {
/**
* 文件所有者名称
*/
private String ownerName;
/**
* 文件下载次数
*/
private long downCount;
}

View File

@ -1,61 +0,0 @@
package cn.wzpmc.filemanager.entities.files;
import cn.wzpmc.filemanager.entities.files.enums.FileType;
import cn.wzpmc.filemanager.entities.vo.FileVo;
import cn.wzpmc.filemanager.entities.vo.FolderVo;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@JSONCompiled
public class RawFileObject {
/**
* 文件ID
*/
private long id;
/**
* 文件名
*/
private String name;
/**
* 文件扩展名文件夹为null
*/
private String ext;
/**
* 文件大小文件夹为-1
*/
private long size;
/**
* 文件所有者
*/
private long owner;
/**
* 父文件夹ID
*/
private long parent;
/**
* 文件上传时间
*/
private Date time;
/**
* 文件类型
*/
private FileType type;
public static RawFileObject of(FileVo file) {
return new RawFileObject(file.getId(), file.getName(), file.getExt(), file.getSize(), file.getUploader(), file.getFolder(), file.getUploadTime(), FileType.FILE);
}
public static RawFileObject of(FolderVo folder) {
return new RawFileObject(folder.getId(), folder.getName(), null, -1, folder.getCreator(), folder.getParent(), folder.getCreateTime(), FileType.FOLDER);
}
public static String getRawFileName(RawFileObject object){
return object.type.equals(FileType.FILE) ? object.getName() + '.' + object.getExt() : object.getName();
}
}

View File

@ -1,15 +0,0 @@
package cn.wzpmc.filemanager.entities.files.enums;
import com.alibaba.fastjson2.annotation.JSONCompiled;
@JSONCompiled
public enum FileType {
/**
* 文件
*/
FILE,
/**
* 文件夹
*/
FOLDER
}

View File

@ -1,35 +0,0 @@
package cn.wzpmc.filemanager.entities.files.enums;
import com.mybatisflex.core.query.QueryColumn;
import lombok.RequiredArgsConstructor;
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
@RequiredArgsConstructor
public enum SortField {
/**
* 通过ID排序默认
*/
ID(FULL_RAW_FILE_OBJECT.ID),
/**
* 通过文件夹排序
*/
NAME(FULL_RAW_FILE_OBJECT.NAME),
/**
* 通过文件扩展名排序
*/
EXT(FULL_RAW_FILE_OBJECT.EXT),
/**
* 通过文件上传时间排序
*/
TIME(FULL_RAW_FILE_OBJECT.TIME),
/**
* 通过文件上传者排序
*/
UPLOADER(FULL_RAW_FILE_OBJECT.OWNER),
/**
* 通过文件下载次数排序
*/
DOWNLOAD_COUNT(FULL_RAW_FILE_OBJECT.DOWN_COUNT);
public final QueryColumn column;
}

View File

@ -1,39 +0,0 @@
package cn.wzpmc.filemanager.entities.statistics.enums;
import com.alibaba.fastjson2.annotation.JSONCompiled;
@JSONCompiled
public enum Actions {
/**
* 文件上传事件
*/
UPLOAD,
/**
* 文件删除事件
*/
DELETE,
/**
* 访问页面事件
*/
ACCESS,
/**
* 文件下载事件
*/
DOWNLOAD,
/**
* 搜索文件事件
*/
SEARCH,
/**
* 登录事件
*/
LOGIN,
/**
* 获取邀请码事件
*/
INVITE,
/**
* 注册事件
*/
REGISTER
}

View File

@ -1,17 +0,0 @@
package cn.wzpmc.filemanager.entities.user;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import lombok.Data;
@Data
@JSONCompiled
public class UserLoginRequest {
/**
* 用户名
*/
private String username;
/**
* 密码通过MD5摘要
*/
private String password;
}

View File

@ -1,26 +0,0 @@
package cn.wzpmc.filemanager.entities.user;
import cn.wzpmc.filemanager.entities.user.enums.Auth;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import lombok.Data;
@Data
@JSONCompiled
public class UserRegisterRequest {
/**
* 用户名
*/
private String username;
/**
* 密码经过MD5摘要
*/
private String password;
/**
* 用户类型
*/
private Auth auth;
/**
* 邀请码当作为admin管理员注册时需填写若作为user普通用户注册时无需
*/
private String inviteCode;
}

View File

@ -1,21 +0,0 @@
package cn.wzpmc.filemanager.entities.user.enums;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.EnumValue;
import lombok.AllArgsConstructor;
@AllArgsConstructor
@JSONCompiled
public enum Auth {
/**
* 管理员
*/
admin(1, "admin"),
/**
* 普通用户
*/
user(0, "user");
public final int value;
@EnumValue
public final String name;
}

View File

@ -1,26 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
@Table("chunk_file")
@Data
@AllArgsConstructor
public class ChunkFileVo {
/**
* 区块ID
*/
@Column("chunk_id")
private long chunkId;
/**
* 文件ID
*/
@Column("file_id")
private long fileId;
/**
* 区块顺序下标从0开始
*/
private long index;
}

View File

@ -1,24 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
@Table("chunks")
@Data
public class ChunksVo {
/**
* 区块ID
*/
@Id(keyType = KeyType.Auto)
private long id;
/**
* 区块哈希值
*/
private String hash;
/**
* 区块大小
*/
private long size;
}

View File

@ -0,0 +1,12 @@
package cn.wzpmc.filemanager.entities.vo;
import lombok.Data;
import java.net.InetAddress;
import java.net.SocketAddress;
@Data
public class DownloadEntryVo {
private String remoteAddr;
private int fileId;
}

View File

@ -0,0 +1,17 @@
package cn.wzpmc.filemanager.entities.vo;
import lombok.Data;
import java.util.Date;
@Data
public class FileObjectVo {
private int id;
private String name;
private String type;
private long size;
private String hash;
private String uploaderName;
private Date uploadTime;
private int downloadCount;
}

View File

@ -1,56 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Table("file")
@Data
@JSONCompiled
public class FileVo implements Serializable {
/**
* 文件ID
*/
@Id(keyType = KeyType.Auto)
private long id;
/**
* 文件名
*/
private String name;
/**
* 文件扩展名
*/
private String ext;
/**
* 文件的MIME类型
*/
private String mime;
/**
* 文件的Sha512哈希值
*/
private String hash;
/**
* 文件的上传者ID
*/
private long uploader;
/**
* 文件的父文件夹ID
*/
private long folder;
/**
* 文件的大小 (bytes)
*/
private long size;
/**
* 文件的上传时间
*/
@Column(onInsertValue = "now()")
private Date uploadTime;
}

View File

@ -1,39 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import java.util.Date;
@Table("folder")
@Data
@JSONCompiled
public class FolderVo {
/**
* 文件夹ID
*/
@Id(keyType = KeyType.Auto)
private long id;
/**
* 文件夹名
*/
private String name;
/**
* 文件夹的父文件夹ID
*/
private long parent;
/**
* 文件夹的创建者
*/
private long creator;
/**
* 文件夹的创建时间
*/
@Column(onInsertValue = "now()")
private Date createTime;
}

View File

@ -1,48 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import cn.wzpmc.filemanager.entities.statistics.enums.Actions;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.lang.Nullable;
import java.util.Date;
@Table("statistics")
@Data
@NoArgsConstructor
@JSONCompiled
public class StatisticsVo {
/***
* 操作者可能为空
*/
@Nullable
private Long actor;
/**
* 具体操作
*/
private Actions action;
/**
* 操作参数一般为JSON字符串
*/
private String params;
/**
* 操作时间
*/
@Column(onInsertValue = "now()")
private Date time;
/**
* 若为下载操作时的下载文件ID
* @ignore
*/
@Column(value = "download_file_id", ignore = true)
private Integer downloadFileId;
public StatisticsVo(@Nullable Long actor, Actions action, String params) {
this.actor = actor;
this.action = action;
this.params = params;
}
}

View File

@ -0,0 +1,11 @@
package cn.wzpmc.filemanager.entities.vo;
import cn.wzpmc.filemanager.entities.abs.PasswordObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UserLoginVo extends PasswordObject {
private String name;
}

View File

@ -0,0 +1,20 @@
package cn.wzpmc.filemanager.entities.vo;
import cn.wzpmc.filemanager.entities.abs.PasswordObject;
import cn.wzpmc.filemanager.enums.Auth;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Objects;
@EqualsAndHashCode(callSuper = true)
@Data
public class UserRegisterVo extends PasswordObject {
private String name;
private Auth auth;
private String verifyCode;
private final static String EMPTY_PASSWORD = "d41d8cd98f00b204e9800998ecf8427e";
public boolean isEmptyNamePassword(){
return Objects.isNull(name) || Objects.equals(EMPTY_PASSWORD, super.password);
}
}

View File

@ -1,63 +0,0 @@
package cn.wzpmc.filemanager.entities.vo;
import cn.wzpmc.filemanager.entities.user.enums.Auth;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
@Table("user")
@Data
@AllArgsConstructor
@JSONCompiled
public class UserVo {
/**
* 用户ID
*/
@Id(keyType = KeyType.Auto)
private long id;
/**
* 用户名
*/
private String name;
/**
* 用户密码
* @ignore
*/
private String password;
/**
* 用户类型
*/
private Auth auth;
/**
* 用户是否被封禁
* `尽管封了你也看不到就是了`
*/
@Column(isLogicDelete = true, onInsertValue = "0")
private boolean banned;
public UserVo(String name, String password, Auth auth) {
this.name = name;
this.password = password;
this.auth = auth;
}
private UserVo(long id, String name, Auth auth) {
this.id = id;
this.name = name;
this.auth = auth;
}
public UserVo(long id) {
this.id = id;
}
public void clearPassword() {
this.setPassword(null);
}
public static final UserVo CONSOLE = new UserVo(0L, "CONSOLE", Auth.admin);
}

View File

@ -1,8 +0,0 @@
package cn.wzpmc.filemanager.entities.vo.table.custom;
import com.mybatisflex.core.query.QueryColumn;
public class StatisticsVoTableDef extends cn.wzpmc.filemanager.entities.vo.table.StatisticsVoTableDef {
public static final StatisticsVoTableDef STATISTICS_VO_EXT = new StatisticsVoTableDef();
public final QueryColumn DOWNLOAD_FILE_ID = new QueryColumn(this, "download_file_id");
}

View File

@ -0,0 +1,5 @@
package cn.wzpmc.filemanager.enums;
public enum Auth {
user,admin;
}

View File

@ -0,0 +1,57 @@
package cn.wzpmc.filemanager.enums;
import lombok.Getter;
@Getter
public enum HttpCodes {
/**
* 200
* 成功执行
*/
HTTP_CODES200(200,"接口执行成功"),
/**
* 500
* 服务器错误
*/
HTTP_CODES500(500,"服务器出现错误,请联系服务器管理员"),
/**
* 401
* 数据错误
*/
HTTP_CODES401(401,"这是一个坏的请求,请重新写入参数"),
/**
* 404
* 找不到文件
*/
FILE_NOT_FOUND(404,"找不到文件"),
/**
* 555
* 数据更新失败
*/
HTTP_CODES555(555,"数据更新失败"),
/**
* 501
* 账号密码错误
*/
HTTP_CODES501(501,"帐号或密码错误!"),
/**
* 250
* token验证错误
*/
INVALID_TOKEN(250,"令牌验证错误"),
/**
* 251
* 无权限访问
*/
ACCESS_DENIED( 251,"无权访问");
private final int code;
private final String message;
HttpCodes(int code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,5 @@
package cn.wzpmc.filemanager.enums;
public enum SearchType {
FILE_NAME, ID, UPLOADER, UPLOAD_DAY, TYPE
}

View File

@ -1,29 +0,0 @@
package cn.wzpmc.filemanager.events;
import cn.wzpmc.filemanager.mapper.InitializationMapper;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.ConsoleMessageCollector;
import com.mybatisflex.core.audit.MessageCollector;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class StartEventListener {
private final InitializationMapper initializationMapper;
@EventListener
public void onStart(ApplicationStartedEvent ignored) {
initializationMapper.createUserTable();
initializationMapper.createStatisticsTable();
initializationMapper.createFolderTable();
initializationMapper.createFileTable();
initializationMapper.createRawFileView();
//开启审计功能
AuditManager.setAuditEnable(true);
MessageCollector collector = new ConsoleMessageCollector();
AuditManager.setMessageCollector(collector);
}
}

View File

@ -1,13 +0,0 @@
package cn.wzpmc.filemanager.exceptions;
import cn.wzpmc.filemanager.entities.Result;
import lombok.Getter;
@Getter
public class AuthorizationException extends RuntimeException {
private final Result<Void> result;
public AuthorizationException(Result<Void> result) {
super(result.getMsg());
this.result = result;
}
}

View File

@ -1,14 +0,0 @@
package cn.wzpmc.filemanager.interfaces;
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
import cn.wzpmc.filemanager.entities.files.RawFileObject;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
public interface FilePathService {
@NonNull
String getFilePath(@NonNull RawFileObject file);
@Nullable
FullRawFileObject resolveFile(@NonNull String[] path);
}

View File

@ -1,67 +0,0 @@
package cn.wzpmc.filemanager.interfaces.impl;
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
import cn.wzpmc.filemanager.mapper.FileMapper;
import cn.wzpmc.filemanager.mapper.FolderMapper;
import cn.wzpmc.filemanager.mapper.RawFileMapper;
import com.mybatisflex.core.query.QueryCondition;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Date;
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
@Component
@Primary
@Log4j2
public class ComplexResolver extends SimplePathResolver {
private final ReverseResolver reverseResolver;
private final SimpleResolver simpleResolver;
private final RawFileMapper rawFileMapper;
@Autowired
public ComplexResolver(FileMapper fileMapper, FolderMapper folderMapper, ReverseResolver reverseResolver, SimpleResolver simpleResolver, RawFileMapper rawFileMapper) {
super(fileMapper, folderMapper);
this.reverseResolver = reverseResolver;
this.simpleResolver = simpleResolver;
this.rawFileMapper = rawFileMapper;
}
@Override
@Nullable
public FullRawFileObject resolveFile(@NonNull String[] path) {
String strPath = Arrays.toString(path);
String targetFileName = path[path.length - 1];
int lastDotIndex = targetFileName.lastIndexOf('.');
String name = targetFileName;
String ext = "";
if (lastDotIndex != -1) {
name = targetFileName.substring(0, lastDotIndex);
ext = targetFileName.substring(lastDotIndex + 1);
}
long start = new Date().getTime();
QueryCondition extCondition = FULL_RAW_FILE_OBJECT.EXT.eq(ext);
if (ext.isEmpty()) {
extCondition = extCondition.or(FULL_RAW_FILE_OBJECT.EXT.isNull());
}
long totalRawFileCount = this.rawFileMapper.selectCountByCondition(FULL_RAW_FILE_OBJECT.NAME.eq(name).and(extCondition));
if (totalRawFileCount == 0) return null;
if (totalRawFileCount > path.length) {
log.info("use simple resolver to solve path with {}", strPath);
FullRawFileObject rawFileObject = simpleResolver.resolveFile(path);
long end = new Date().getTime();
log.info("solve path {} cost {}ms", strPath, end - start);
return rawFileObject;
}
log.info("use reverse resolver to solve path with {}", strPath);
FullRawFileObject rawFileObject = reverseResolver.resolveFile(path);
long end = new Date().getTime();
log.info("solve path {} cost {}ms", strPath, end - start);
return rawFileObject;
}
}

Some files were not shown because too many files have changed in this diff Show More