目前项目选择fastdfs作为服务中心,就用spring cloud + fastdfsClient作为文件管理的框架
这是pom.xml文件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId> //用eure可作为服务发现框架
</dependency>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId> //fastdfs-client
<version>1.27.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId> //接口说明文档
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
Application 里面的注解
@EnableDiscoveryClient@SpringBootApplication@Configuration@EnableSwagger2public class FilemanagerApplication { public static void main(String[] args) { SpringApplication.run(FilemanagerApplication.class, args); }}
swagger配置在加载配置是
通过注解EnableSwagger2声明Swagger的可用性,此处会定义一个类型为Docket的bean,
关于docket类的说明如下:
A builder which is intended to be the primary interface into the swagger-springmvc framework.Provides sensible defaults and convenience methods for configuration.
Docket的select()方法会提供给swagger-springmvc framework的一个默认构造器(ApiSelectorBuilder),这个构造器为配置swagger提供了一系列的默认属性和便利方法。
@Configuration@EnableSwagger2public class SwaggerConfig { @Bean public Docket computeRestApi() { return new Docket(DocumentationType.SWAGGER_2).groupName("filenamager") .select() // 选择那些路径和api会生成document .apis(RequestHandlerSelectors.basePackage("com.cloud.fastdfs.filemanager.control")) // 拦截的包路径 .paths(PathSelectors.any())// 拦截的接口路径 .build(); } private ApiInfo computeApiInfo() { Contact contact = new Contact("XXXX", "XXXX", "XXXXX"); ApiInfo apiInfo = new ApiInfoBuilder() .title("并行计算服务 - API接口") .description("REST风格API") .contact(contact) .version("1.0") .build(); return apiInfo; }}
fastdfsClient 的使用方式
@Componentpublic class FastDFSClient { @Autowired private FastConnectionPool connectionPool; public String uploadFile(byte[] buff,String fileName) { return uploadFile(buff, fileName, null,null); } public String uploadFile(byte[] buff, String fileName, Map<String, String> metaList,String groupName) { try { NameValuePair[] nameValuePairs = null; if (metaList != null) { nameValuePairs = new NameValuePair[metaList.size()]; int index = 0; for (Iterator<Map.Entry<String, String>> iterator = metaList.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry<String, String> entry = iterator.next(); String name = entry.getKey(); String value = entry.getValue(); nameValuePairs[index++] = new NameValuePair(name, value); } } /** 获取可用的tracker,并创建存储server */ StorageClient1 storageClient = connectionPool.checkout(); String path = null; if (!StringUtils.isEmpty(groupName)) { // 上传到指定分组 path = storageClient.upload_file1(groupName, buff, FileUtil.getExtensionName(fileName), nameValuePairs); } else { path = storageClient.upload_file1(buff, FileUtil.getExtensionName(fileName), nameValuePairs); } /** 上传完毕及时释放连接 */ connectionPool.checkin(storageClient); return path; } catch (Exception e) { e.printStackTrace(); } return null; } public Map<String, String> getFileMetadata(String fileId) { try { /** 获取可用的tracker,并创建存储server */ StorageClient1 storageClient = connectionPool.checkout(); NameValuePair[] metaList = storageClient.get_metadata1(fileId); /** 上传完毕及时释放连接 */ connectionPool.checkin(storageClient); if (metaList != null) { HashMap<String, String> map = new HashMap<String, String>(); for (NameValuePair metaItem : metaList) { map.put(metaItem.getName(), metaItem.getValue()); } return map; } } catch (Exception e) { e.printStackTrace(); } return null; } public int deleteFile(String fileId) { try { /** 获取可用的tracker,并创建存储server */ StorageClient1 storageClient = connectionPool.checkout(); int i = storageClient.delete_file1(fileId); /** 上传完毕及时释放连接 */ connectionPool.checkin(storageClient); return i; } catch (Exception e) { e.printStackTrace(); } return -1; } public byte[] downloadFile(String fileId) { try { /** 获取可用的tracker,并创建存储server */ StorageClient1 storageClient = connectionPool.checkout(); byte[] content = storageClient.download_file1(fileId); /** 上传完毕及时释放连接 */ connectionPool.checkin(storageClient); return content; } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } public FileInfo getFileInfo(String fileId) { try { /** 获取可用的tracker,并创建存储server */ StorageClient1 storageClient = connectionPool.checkout(); FileInfo fileInfo = storageClient.get_file_info1(fileId); /** 上传完毕及时释放连接 */ connectionPool.checkin(storageClient); return fileInfo; } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; }}
FastDFS client 连接池实现
@Componentpublic class FastConnectionPool { private static final String FASTDFS_CONFIG = "client.conf"; /*空闲的连接池*/ private LinkedBlockingQueue<StorageClient1> idleConnectionPool = null; /** 连接池默认最小连接数 */ private long minPoolSize = 10; /** 连接池默认最大连接数 */ private long maxPoolSize = 30; /** 默认等待时间(单位:秒) */ private long waitTimes = 200; /** fastdfs客户端创建连接默认1次 */ private static final int COUNT = 1; private Object obj = new Object(); TrackerServer trackerServer = null; public FastConnectionPool() { /** 初始化连接池 */ poolInit(); /** 注册心跳 */ //HeartBeat beat = new HeartBeat(this); //beat.beat(); } public FastConnectionPool(long minPoolSize, long maxPoolSize, long waitTimes) { System.out.println("[线程池构造方法(ConnectionPool)][默认参数:minPoolSize=" + minPoolSize + ",maxPoolSize=" + maxPoolSize + ",waitTimes=" + waitTimes + "]"); this.minPoolSize = minPoolSize; this.maxPoolSize = maxPoolSize; this.waitTimes = waitTimes; /** 初始化连接池 */ poolInit(); /** 注册心跳 */ // HeartBeat beat = new HeartBeat(this); //beat.beat(); } private void poolInit() { try { /** 加载配置文件 */ initClientGlobal(); /** 初始化空闲连接池 */ idleConnectionPool = new LinkedBlockingQueue<StorageClient1>(); /** 初始化忙碌连接池 */ // busyConnectionPool = new ConcurrentHashMap<StorageClient1, Object>(); TrackerClient trackerClient = new TrackerClient(); trackerServer = trackerClient.getConnection(); int flag = 0; while (trackerServer == null && flag < 5) { System.out.println("[创建TrackerServer(createTrackerServer)][第" + flag + "次重建]"); flag++ ; initClientGlobal(); trackerServer = trackerClient.getConnection(); } // 测试 Tracker活跃情况 // ProtoCommon.activeTest(trackerServer.getSocket()); /** 往线程池中添加默认大小的线程 */ createTrackerServer(); } catch (Exception e) { e.printStackTrace(); System.out.println("[FASTDFS初始化(init)--异常]"); } } public void createTrackerServer() { System.out.println("[创建TrackerServer(createTrackerServer)]"); TrackerServer trackerServer = null; try { for (int i = 0; i < minPoolSize; i++ ) { // 把client1添加到连接池 StorageServer storageServer = null; StorageClient1 client1 = new StorageClient1(trackerServer, storageServer); idleConnectionPool.add(client1); } } catch (Exception e) { e.printStackTrace(); System.out.println("[创建TrackerServer(createTrackerServer)][异常:{}]"); } } public StorageClient1 checkout() { StorageClient1 client1 = idleConnectionPool.poll(); if (client1 == null) { if (idleConnectionPool.size() < maxPoolSize) { createTrackerServer(); try { client1 = idleConnectionPool.poll(waitTimes, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); System.out.println("[获取空闲连接(checkout)-error][error:获取连接超时:{}]"); } } } // 添加到忙碌连接池 // busyConnectionPool.put(client1, obj); System.out.println("[获取空闲连接(checkout)][获取空闲连接成功]"); return client1; } public void checkin(StorageClient1 client1) { System.out.println("[释放当前连接(checkin)]"); client1 = null; if (idleConnectionPool.size() < minPoolSize) { createTrackerServer(); } } private void initClientGlobal() throws Exception { ClientGlobal.init(FASTDFS_CONFIG); } public LinkedBlockingQueue<StorageClient1> getIdleConnectionPool() { return idleConnectionPool; } public long getMinPoolSize() { return minPoolSize; } public void setMinPoolSize(long minPoolSize) { if (minPoolSize != 0) { this.minPoolSize = minPoolSize; } } public long getMaxPoolSize() { return maxPoolSize; } public void setMaxPoolSize(long maxPoolSize) { if (maxPoolSize != 0) { this.maxPoolSize = maxPoolSize; } } public long getWaitTimes() { return waitTimes; } public void setWaitTimes(int waitTimes) { if (waitTimes != 0) { this.waitTimes = waitTimes; } }}
Controller 两个restful风格接口实现
@Api(value = "filenamager", tags = {"文件管理"})@RestController@RequestMapping("/filenamager/*")public class FileController { Logger logger = LogManager.getLogger(FileController.class); @Autowired private FastDFSClient fastDFSClient; @ApiOperation(value = "文件上传", notes = "文件上传") @RequestMapping(value = "uploadFile",method = RequestMethod.POST) public Map<String, Object> uploadFile(@RequestParam("uploadFile") MultipartFile filedata) { logger.info("lige1:" + filedata.toString()); Map<String, Object> m = new HashMap<String, Object>(); if (filedata != null && !filedata.isEmpty()) { try { String path = fastDFSClient.uploadFile(filedata.getBytes(), filedata.getOriginalFilename()); m.put("code", Code.SUCCESS); m.put("url", path); m.put("msg", "上传成功"); } catch (Exception e) { e.printStackTrace(); m.put("code", Code.FAIL); m.put("msg", "上传失败"); } } else { m.put("code", Code.PARAMETER_LOST); m.put("msg", "参数丢失"); } return m; } @ApiOperation(value = "下载文件", notes = "下载文件") @ApiImplicitParam(name = "path", value = "路径", required = true, dataType = "String") @RequestMapping(value = "getFileByPath", method = RequestMethod.GET) public void getFileByPath(HttpServletResponse response, String path) { try { // 判断文件是否存在 if (fastDFSClient.getFileInfo(path) != null) { byte[] buffer = fastDFSClient.downloadFile(path); // 清空response response.reset(); // 设置response的Header response.addHeader("Content-Disposition", "attachment;filename=" + FileUtil.getOriginalFilename(path)); response.addHeader("Content-Length", "" + buffer.length); // 通过文件流的形式写到客户端 OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/octet-stream"); toClient.write(buffer); // 写完以后关闭文件流 toClient.flush(); toClient.close(); } } catch (IOException e) { e.printStackTrace(); } }}
application.yml文件配置
server: port: 9010 tomcat: uri-encoding: UTF-8eureka: instance: hostname: eureka-server prefer-ip-address: true client: service-url: defaultZone: http://localhost:9001/eureka/spring: application: name: cloud-fastdfs-filemanager
fastdfs client相关配置就不贴了,直接从fast安装环境下取个client.conf改改就可以用了。
下面写下怎么通过httpclient 4.5来访问相关接口
public static void uploadFile(String filePath,String FileUploadURL) { client = new DefaultHttpClient(); File targetFile = new File(filePath); try { if (targetFile == null || !targetFile.exists()) { throw new FileNotFoundException(); } MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder .addBinaryBody("uploadFile", targetFile) .setMode(HttpMultipartMode.RFC6532); HttpPost httpPost = new HttpPost(FileUploadURL); httpPost.setEntity(multipartEntityBuilder.build()); HttpResponse httpResponse = client.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); String content = EntityUtils.toString(httpEntity); System.out.println(content); } catch(Exception e) { e.printStackTrace(); }}
{"msg":"上传成功","code":"SUCCESS","url":"group1/M00/00/00/CgEDEFp_3eKASSzfAABEs-HwdPA11.xlsx"}
执行结果