Przeglądaj źródła

增加文件上传模块

zhou-hao 5 lat temu
rodzic
commit
5301b0bb98

+ 53 - 0
hsweb-system/hsweb-system-file/pom.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hsweb-system</artifactId>
+        <groupId>org.hswebframework.web</groupId>
+        <version>4.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>hsweb-system-file</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webflux</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-test-autoconfigure</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>

+ 25 - 0
hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileServiceConfiguration.java

@@ -0,0 +1,25 @@
+package org.hswebframework.web.file;
+
+import org.hswebframework.web.file.web.ReactiveFileController;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableConfigurationProperties(FileUploadProperties.class)
+public class FileServiceConfiguration {
+
+
+    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
+    static class ReactiveConfiguration {
+
+        @Bean
+        @ConditionalOnMissingBean(name = "reactiveFileController")
+        private ReactiveFileController reactiveFileController() {
+            return new ReactiveFileController();
+        }
+    }
+
+}

+ 46 - 0
hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java

@@ -0,0 +1,46 @@
+package org.hswebframework.web.file;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.utils.time.DateFormatter;
+import org.hswebframework.web.id.IDGenerator;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.io.File;
+import java.util.Date;
+
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "hsweb.file.upload")
+public class FileUploadProperties {
+
+    private String staticFilePath = "./static";
+
+    private String staticLocation = "/static";
+
+
+    public StaticFileInfo createStaticSavePath(String name) {
+        String fileName = IDGenerator.SNOW_FLAKE_STRING.generate();
+        String filePath = DateFormatter.toString(new Date(), "yyyyMMdd");
+        String absPath = staticFilePath.concat("/").concat(filePath);
+        //文件后缀
+        String suffix =  name.contains(".") ?
+                name.substring(name.lastIndexOf(".")) : "";
+
+        new File(absPath).mkdirs();
+        StaticFileInfo info = new StaticFileInfo();
+
+        info.location = staticLocation + "/" + fileName + suffix;
+        info.savePath = absPath + "/" + fileName + suffix;
+
+        return info;
+    }
+
+    @Getter
+    @Setter
+    public class StaticFileInfo {
+        private String savePath;
+
+        private String location;
+    }
+}

+ 54 - 0
hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/web/ReactiveFileController.java

@@ -0,0 +1,54 @@
+package org.hswebframework.web.file.web;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.authorization.annotation.ResourceAction;
+import org.hswebframework.web.file.FileUploadProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.codec.multipart.FilePart;
+import org.springframework.http.codec.multipart.Part;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+
+@RestController
+@Resource(id = "file", name = "文件上传")
+@Slf4j
+@RequestMapping("/file")
+public class ReactiveFileController {
+
+    @Autowired
+    private FileUploadProperties properties;
+
+    @ResourceAction(id = "upload-static", name = "静态文件")
+    @PostMapping("/static")
+    @SneakyThrows
+    public Mono<String> uploadStatic(@RequestPart("file") Part part) {
+        FileUploadProperties.StaticFileInfo name ;
+        if(part instanceof FilePart){
+            name = properties.createStaticSavePath(((FilePart)part).filename());
+            return ((FilePart)part)
+                    .transferTo(new File(name.getSavePath()))
+                    .thenReturn(name.getLocation());
+        }else{
+           return Mono.error(()->new IllegalArgumentException("[file] part is not a file"));
+        }
+
+    }
+
+}

+ 3 - 0
hsweb-system/hsweb-system-file/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,3 @@
+# Auto Configure
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.hswebframework.web.file.FileServiceConfiguration

+ 48 - 0
hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/ReactiveFileControllerTest.java

@@ -0,0 +1,48 @@
+package org.hswebframework.web.file.web;
+
+import org.hswebframework.web.file.FileServiceConfiguration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.BodyInserters;
+
+import static org.junit.Assert.*;
+
+@WebFluxTest(ReactiveFileController.class)
+@RunWith(SpringRunner.class)
+@ImportAutoConfiguration(FileServiceConfiguration.class)
+public class ReactiveFileControllerTest {
+
+    static {
+        System.setProperty("hsweb.file.upload.static-file-path","./target/upload");
+    }
+
+    @Autowired
+    WebTestClient client;
+
+    @Test
+    public void test(){
+       client.post()
+                .uri("/file/static")
+               .contentType(MediaType.MULTIPART_FORM_DATA)
+               .body(BodyInserters.fromMultipartData("file",new HttpEntity<>(new ClassPathResource("test.json"))))
+               .exchange()
+                .expectStatus()
+               .isOk();
+
+    }
+}

+ 7 - 0
hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/TestApplication.java

@@ -0,0 +1,7 @@
+package org.hswebframework.web.file.web;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class TestApplication {
+}

+ 3 - 0
hsweb-system/hsweb-system-file/src/test/resources/test.json

@@ -0,0 +1,3 @@
+{
+  "a": "b"
+}

+ 1 - 0
hsweb-system/pom.xml

@@ -13,6 +13,7 @@
     <packaging>pom</packaging>
     <modules>
         <module>hsweb-system-authorization</module>
+        <module>hsweb-system-file</module>
     </modules>
     <artifactId>hsweb-system</artifactId>