docker 安装 delron/fastdfs
4.使用docker镜像构建tracker容器(跟踪服务器,起到调度的作用):
docker run -dti --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs -v /etc/localtime:/etc/localtime delron/fastdfs tracker
5.使用docker镜像构建storage容器(存储服务器,提供容量和备份服务):
docker run -dti --network=host --name storage -e TRACKER_SERVER=192.168.56.1:22122 -v /var/fdfs/storage:/var/fdfs -v /etc/localtime:/etc/localtime delron/fastdfs storage
TRACKER_SERVER=本机的ip地址:22122 本机ip地址不要使用127.0.0.1
进入storage容器,到storage的配置文件中配置http访问的端口,配置文件在/etc/fdfs目录下的storage.conf。
默认端口是8888,也可以不进行更改。
如果重启后无法启动的会,可能是报下面错误了,手动创建 vi /var/fdfs/logs/storaged.log 文件即可
tail: cannot open '/var/fdfs/logs/storaged.log' for reading: No such file or directory
6.配置nginx
进入storage,配置nginx,在/usr/local/nginx目录下,修改nginx.conf文件,默认配置不修改也可以
7.测试上传文件
使用web模块进行文件的上传,将文件上传至FastDFS文件系统
将一张照片(test.png)放置在/var/fdfs/storage目录下,进入storage容器,进入/var/fdfs目录,运行下面命令:
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf test.png
此时将该图片已上传至文件系统,并在执行该语句后返回图片存储的uri:
通过url访问http://ip:8888/group1/M00/00/00/CgACD1z7SEuAXrIqAA1eBLGVLow043.png,即可查看到图片
8.开放端口 必须全部开放
firewall-cmd --zone=public --permanent --add-port=8888/tcp
firewall-cmd --zone=public --permanent --add-port=22122/tcp
firewall-cmd --zone=public --permanent --add-port=23000/tcp
重启防火墙
systemctl restart firewalld
9.开启启动容器
docker update --restart=always tracker
docker update --restart=always storage
10.常见问题
storage 无法启动
运行 docker container start storage 无法启动,进行如下操作即可:
可以删除/var/fdfs/storage/data目录下的fdfs_storaged.pid 文件,然后重新运行storage。
fdfs_client.conf
connect_timeout = 20 network_timeout = 30 charset = UTF-8 http.tracker_http_port = 9004 http.anti_steal_token = no http.secret_key = FastDFS1234567890 #开发上传地址 tracker_server = 10.10.0.25:22122 #tracker_server = 192.168.3.138:22122
自定义实体类FastDFSFile
public class FastDFSFile { private String name;//文件名 private byte[] content; //文件的内容,字节数组 private String ext; //文件扩展名,不包含(.) private String md5; //加密 private String author; public FastDFSFile() { } public FastDFSFile(String name, byte[] content, String ext) { 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; } }
创建 FastDFSClient工具类
public class FastDFSClient { private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class); static { try { String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();; ClientGlobal.init(filePath); } catch (Exception e) { logger.error("FastDFS Client Init Fail!",e); } } /** * 文件上传 * @param file 自定义文件上传类 * @return */ 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; StorageClient storageClient=null; try { storageClient = getTrackerClient(); //upload_file()三个参数:@param fileContent ①:文件的内容,字节数组 ②:文件扩展名 ③文件扩展信息 数组 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 && storageClient!=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); return uploadResults; } /** * 查询文件信息 * @param groupName * @param remoteFileName * @return */ public static FileInfo getFile(String groupName, String remoteFileName) { try { StorageClient storageClient = getTrackerClient(); 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; } /** * 下载文件 * @param groupName 文件路径 * @param remoteFileName 输出流 中包含要输出到磁盘的路径 * @return */ public static InputStream downFile(String groupName, String remoteFileName) { try { StorageClient storageClient = getTrackerClient(); 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; } /** * 删除文件 * ==0表示成功 * @param groupName 组名 如:group1 * @param remoteFileName 不带组名的路径名称 如:M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg * @throws Exception */ public static int deleteFile(String groupName, String remoteFileName) throws Exception { StorageClient storageClient = getTrackerClient(); return storageClient.delete_file(groupName, remoteFileName); } /** * 获取storage * @param groupName 组名 * @return * @throws IOException */ public static StorageServer[] getStoreStorages(String groupName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getStoreStorages(trackerServer, groupName); } /** * * @param groupName * @param remoteFileName * @return * @throws IOException */ public static ServerInfo[] getFetchStorages(String groupName,String remoteFileName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); } /** * 获取reacker地址 * @return * @throws IOException */ public static String getTrackerUrl() throws IOException { return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ ClientGlobal.getG_tracker_http_port()+"/"; } /** * 获取tracker连接 * @return * @throws IOException */ private static StorageClient getTrackerClient() throws IOException { TrackerServer trackerServer = getTrackerServer(); StorageClient storageClient = new StorageClient(trackerServer, null); return storageClient; } /** * 获取tracker服务 * @return * @throws IOException */ private static TrackerServer getTrackerServer() throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerServer; } }
controller
/** * fastdfs 文件上传 */ @RequestMapping(method = RequestMethod.POST, value = "/upload") @ResponseBody public Object fileUploadByFdfs(@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 path=saveFile(file); redirectAttributes.addFlashAttribute("message", "You successfully uploaded '" + file.getOriginalFilename() + "'"); redirectAttributes.addFlashAttribute("path", "file path url '" + path + "'"); return path; } catch (Exception e) { logger.error("upload file failed",e); } return "error"; } /** * @param multipartFile * @return * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试 */ public String saveFile(MultipartFile multipartFile) throws IOException { String[] fileAbsolutePath={}; String fileName=multipartFile.getOriginalFilename(); String ext = fileName.substring(fileName.lastIndexOf(".") + 1); 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 e) { logger.error("upload file Exception!",e); } if (fileAbsolutePath==null) { logger.error("upload file failed,please upload again!"); } String path = fileAbsolutePath[0]+ "/"+fileAbsolutePath[1]; return path; }