From ecca616618060127401ddb67752280a6cd7be609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BA=AF=E6=B4=81=E7=9A=84=E5=BE=AE=E7=AC=91?= Date: Fri, 13 Oct 2017 17:17:56 +0800 Subject: [PATCH] spring-boot-fastDFS --- .../fastdfs-client-java-1.27-SNAPSHOT.jar | Bin 0 -> 62567 bytes spring-boot-fastDFS/pom.xml | 52 +++++++++ .../main/java/com/neo/FastDFSApplication.java | 34 ++++++ .../java/com/neo/config/Configurations.java | 19 ++++ .../controller/GlobalExceptionHandler.java | 20 ++++ .../com/neo/controller/UploadController.java | 93 ++++++++++++++++ .../java/com/neo/fastdfs/FastDFSClient.java | 104 ++++++++++++++++++ .../java/com/neo/fastdfs/FastDFSFile.java | 70 ++++++++++++ .../src/main/resources/application.properties | 6 + .../src/main/resources/fdfs_client.conf | 9 ++ .../src/main/resources/logback.xml | 24 ++++ .../src/main/resources/templates/upload.html | 13 +++ .../resources/templates/uploadStatus.html | 16 +++ 13 files changed, 460 insertions(+) create mode 100644 spring-boot-fastDFS/fastdfs-client-java-1.27-SNAPSHOT.jar create mode 100644 spring-boot-fastDFS/pom.xml create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/config/Configurations.java create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java create mode 100644 spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java create mode 100644 spring-boot-fastDFS/src/main/resources/application.properties create mode 100644 spring-boot-fastDFS/src/main/resources/fdfs_client.conf create mode 100644 spring-boot-fastDFS/src/main/resources/logback.xml create mode 100644 spring-boot-fastDFS/src/main/resources/templates/upload.html create mode 100644 spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html diff --git a/spring-boot-fastDFS/fastdfs-client-java-1.27-SNAPSHOT.jar b/spring-boot-fastDFS/fastdfs-client-java-1.27-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..2723cd539f6e9bd8f43078a7620a1d8f395e32d0 GIT binary patch literal 62567 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 z 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 KcifJ?fBSy}yc9_Q literal 0 HcmV?d00001 diff --git a/spring-boot-fastDFS/pom.xml b/spring-boot-fastDFS/pom.xml new file mode 100644 index 0000000..7aa2d49 --- /dev/null +++ b/spring-boot-fastDFS/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + com.neo + spring-boot-fastDFS + jar + 1.0 + + + org.springframework.boot + spring-boot-starter-parent + 1.5.7.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + true + + + org.csource + fastdfs-client-java + 1.27-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java b/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java new file mode 100644 index 0000000..daf1a10 --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java @@ -0,0 +1,34 @@ +package com.neo; + +import org.apache.coyote.http11.AbstractHttp11Protocol; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class FastDFSApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(FastDFSApplication.class, args); + } + + //Tomcat large file upload connection reset + @Bean + public TomcatEmbeddedServletContainerFactory tomcatEmbedded() { + + TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); + + tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { + if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { + //-1 means unlimited + ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); + } + }); + + return tomcat; + + } + +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/config/Configurations.java b/spring-boot-fastDFS/src/main/java/com/neo/config/Configurations.java new file mode 100644 index 0000000..4e1a8f2 --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/config/Configurations.java @@ -0,0 +1,19 @@ +package com.neo.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Configurations { + + @Value("${fastdfs.base.url}") + private String fdfsUrl; + + public String getFdfsUrl() { + return fdfsUrl; + } + + public void setFdfsUrl(String fdfsUrl) { + this.fdfsUrl = fdfsUrl; + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java new file mode 100644 index 0000000..fd6e17c --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java @@ -0,0 +1,20 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@ControllerAdvice +public class GlobalExceptionHandler { + + //https://jira.spring.io/browse/SPR-14651 + //4.3.5 supports RedirectAttributes redirectAttributes + @ExceptionHandler(MultipartException.class) + public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { + + redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); + return "redirect:/uploadStatus"; + + } +} diff --git a/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java b/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java new file mode 100644 index 0000000..a15f417 --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java @@ -0,0 +1,93 @@ +package com.neo.controller; + +import com.neo.config.Configurations; +import com.neo.fastdfs.FastDFSClient; +import com.neo.fastdfs.FastDFSFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +@Controller +public class UploadController { + private static Logger logger = LoggerFactory.getLogger(UploadController.class); + @Autowired + private Configurations configuration; + + @GetMapping("/") + public String index() { + return "upload"; + } + + @PostMapping("/upload") // //new annotation since 4.3 + public String singleFileUpload(@RequestParam("file") MultipartFile file, + RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); + return "redirect:uploadStatus"; + } + + try { + // Get the file and save it somewhere + String name=file.getOriginalFilename(); + String ext = name.substring(name.lastIndexOf(".") + 1); + String path=saveFile(file,name,ext); + redirectAttributes.addFlashAttribute("message", + "You successfully uploaded '" + file.getOriginalFilename() + "'"); + + redirectAttributes.addFlashAttribute("path", + "file path url '" + path + "'"); + + } catch (Exception e) { + logger.error("upload file failed",e); + } + + return "redirect:/uploadStatus"; + } + + @GetMapping("/uploadStatus") + public String uploadStatus() { + return "uploadStatus"; + } + + + + public String saveFile(MultipartFile multipartFile, String fileName, String ext){ + String path=""; + String[] fileAbsolutePath={}; + try { + byte[] file_buff = null; + InputStream inputStream=multipartFile.getInputStream(); + if(inputStream!=null){ + int len1 = inputStream.available(); + file_buff = new byte[len1]; + inputStream.read(file_buff); + } + inputStream.close(); + FastDFSFile file = new FastDFSFile(fileName, file_buff, ext); + try { + fileAbsolutePath = FastDFSClient.upload(file); //upload to fastdfs + } catch (Exception e1) { + e1.printStackTrace(); + } + if (fileAbsolutePath==null) { + System.out.println("upload file failed,please upload again!"); + } + path=configuration.getFdfsUrl()+fileAbsolutePath[0]+ "/"+fileAbsolutePath[1]; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return path; + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java b/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java new file mode 100644 index 0000000..d1047c0 --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java @@ -0,0 +1,104 @@ +package com.neo.fastdfs; + +import org.csource.common.NameValuePair; +import org.csource.fastdfs.*; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.io.*; + + +public class FastDFSClient { + private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class); + private static TrackerClient trackerClient; + private static TrackerServer trackerServer; + private static StorageClient storageClient; + private static StorageServer storageServer; + + static { + try { + Resource resource = new ClassPathResource("fdfs_client.conf"); + File file = resource.getFile(); + String configFile = file.getAbsolutePath(); + + ClientGlobal.init(configFile); + trackerClient = new TrackerClient(); + trackerServer = trackerClient.getConnection(); + storageServer = trackerClient.getStoreStorage(trackerServer); + storageClient = new StorageClient(trackerServer, storageServer); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("FastDFS Client Init Fail!"); + } + } + + public static String[] upload(FastDFSFile file) { + logger.info("File Name: " + file.getName() + "File Length:" + file.getContent().length); + + NameValuePair[] meta_list = new NameValuePair[1]; + meta_list[0] = new NameValuePair("author", file.getAuthor()); + + long startTime = System.currentTimeMillis(); + String[] uploadResults = null; + try { + uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list); + } catch (IOException e) { + logger.error("IO Exception when uploadind the file:" + file.getName(), e); + } catch (Exception e) { + logger.error("Non IO Exception when uploadind the file:" + file.getName(), e); + } + logger.info("upload_file time used:" + (System.currentTimeMillis() - startTime) + " ms"); + + if (uploadResults == null) { + logger.error("upload file fail, error code:" + storageClient.getErrorCode()); + } + String groupName = uploadResults[0]; + String remoteFileName = uploadResults[1]; + + logger.info("upload file successfully!!!" + "group_name:" + groupName + ", remoteFileName:" + " " + remoteFileName); + System.out.println("upload file successfully!!!" + "group_name:" + groupName + ", remoteFileName:" + " " + remoteFileName); + + return uploadResults; + } + + public static FileInfo getFile(String groupName, String remoteFileName) { + try { + return storageClient.get_file_info(groupName, remoteFileName); + } catch (IOException e) { + logger.error("IO Exception: Get File from Fast DFS failed", e); + } catch (Exception e) { + logger.error("Non IO Exception: Get File from Fast DFS failed", e); + } + return null; + } + + public static InputStream downFile(String groupName, String remoteFileName) { + try { + byte[] fileByte = storageClient.download_file(groupName, remoteFileName); + InputStream ins = new ByteArrayInputStream(fileByte); + return ins; + } catch (IOException e) { + logger.error("IO Exception: Get File from Fast DFS failed", e); + } catch (Exception e) { + logger.error("Non IO Exception: Get File from Fast DFS failed", e); + } + return null; + } + + public static void deleteFile(String groupName, String remoteFileName) + throws Exception { + int i = storageClient.delete_file(groupName, remoteFileName); + System.out.println("delete file successfully!!!" + i); + } + + public static StorageServer[] getStoreStorages(String groupName) + throws IOException { + return trackerClient.getStoreStorages(trackerServer, groupName); + } + + public static ServerInfo[] getFetchStorages(String groupName, + String remoteFileName) throws IOException { + return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java b/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java new file mode 100644 index 0000000..adee175 --- /dev/null +++ b/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java @@ -0,0 +1,70 @@ +package com.neo.fastdfs; + +public class FastDFSFile { + private String name; + + private byte[] content; + + private String ext; + + private String md5; + + private String author; + + public FastDFSFile(String name, byte[] content, String ext, String height, + String width, String author) { + super(); + this.name = name; + this.content = content; + this.ext = ext; + this.author = author; + } + + public FastDFSFile(String name, byte[] content, String ext) { + super(); + this.name = name; + this.content = content; + this.ext = ext; + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + public String getExt() { + return ext; + } + + public void setExt(String ext) { + this.ext = ext; + } + + public String getMd5() { + return md5; + } + + public void setMd5(String md5) { + this.md5 = md5; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/resources/application.properties b/spring-boot-fastDFS/src/main/resources/application.properties new file mode 100644 index 0000000..7ec2bb4 --- /dev/null +++ b/spring-boot-fastDFS/src/main/resources/application.properties @@ -0,0 +1,6 @@ +#http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties +#search multipart +spring.http.multipart.max-file-size=10MB +spring.http.multipart.max-request-size=10MB + +fastdfs.base.url=http://192.168.53.85:8080/ \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/resources/fdfs_client.conf b/spring-boot-fastDFS/src/main/resources/fdfs_client.conf new file mode 100644 index 0000000..949c802 --- /dev/null +++ b/spring-boot-fastDFS/src/main/resources/fdfs_client.conf @@ -0,0 +1,9 @@ +connect_timeout = 2 +network_timeout = 30 +charset = UTF-8 +http.tracker_http_port = 8080 +http.anti_steal_token = no +http.secret_key = 123456 + +tracker_server = 192.168.53.85:22122 +tracker_server = 192.168.53.86:22122 diff --git a/spring-boot-fastDFS/src/main/resources/logback.xml b/spring-boot-fastDFS/src/main/resources/logback.xml new file mode 100644 index 0000000..0c0f833 --- /dev/null +++ b/spring-boot-fastDFS/src/main/resources/logback.xml @@ -0,0 +1,24 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/resources/templates/upload.html b/spring-boot-fastDFS/src/main/resources/templates/upload.html new file mode 100644 index 0000000..2e93a58 --- /dev/null +++ b/spring-boot-fastDFS/src/main/resources/templates/upload.html @@ -0,0 +1,13 @@ + + + + +

Spring Boot file upload example

+ +
+

+ +
+ + + diff --git a/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html b/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html new file mode 100644 index 0000000..bcdab68 --- /dev/null +++ b/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html @@ -0,0 +1,16 @@ + + + + +

Spring Boot - Upload Status

+ +
+

+

+ +
+

+

+ + + \ No newline at end of file