FastDFS文件上传失败问题(java.io.IOException: recv package size -1 != 10)

前言

需求分析:本来是一个很简单的操作,往文件服务器上传文件,并将冗余文件进行删除操作。


一、情景再现

1.出事代码

/**
	 * 上传文件
	 * @param file
	 * @return
	 * @throws IOException
	 */
	private String saveFile(FastDfsFile file) throws IOException {

		boolean activeTest = ProtoCommon
				.activeTest(new TrackerClient(ClientGlobal.g_tracker_group).getConnection().getSocket());

		// 相当于发起第一次握手,之后文件上传就是第二次了。
//				org.csource.fastdfs.ProtoCommon.activeTest(trackerServer.getSocket());

		logger.info("File Name: " + file.getFileName() + "File Length:" + file.getFileContent().length);
		NameValuePair[] metaList = new NameValuePair[] { new NameValuePair("author", file.getAuthor()) };
		long startTime = System.currentTimeMillis();
		String[] uploadResults;

		try {
//			storageClient = new StorageClient(trackerServer, storageServer);
			uploadResults = storageClient.upload_file(file.getFileContent(), file.getFileType(), metaList);
		} catch (IOException e) {
			logger.error("IO Exception when uploading the file:" + file.getFileName(), e);
			throw e;
		} catch (MyException var10) {
			logger.error("Non IO Exception when uploading the file:" + file.getFileName(), var10);
			return null;
		}

		logger.info("上传文件耗时:" + (System.currentTimeMillis() - startTime) + " ms");
		if (uploadResults == null) {
			logger.error("upload file fail, error code:" + storageClient.getErrorCode());
			return null;
		} else {
			String groupName = uploadResults[0];
			String remoteFileName = uploadResults[1];
			logger.info("upload file successfully!!!group_name:" + groupName + ", remoteFileName: " + remoteFileName);
			String resultUrl = groupName + "/" + remoteFileName;
			return resultUrl;
		}
	}
	/**
	 * 删除文件
	 */
	@Override
	public EcpResult deleteFile(String groupName, String remoteFileName) {
		try {
			storageClient = new StorageClient(trackerServer, storageServer);
			int i = storageClient.delete_file(groupName, remoteFileName);
			logger.info("delete file successfully!!!" + i);
			return EcpResult.buildDeleteSucess();
		} catch (IOException var4) {
			var4.printStackTrace();
		} catch (MyException var5) {
			var5.printStackTrace();
		}

		return EcpResult.buildQueryFailed();
	}

接口:

    @PostMapping("/save/{eventId}")
    public EcpResult save(@PathVariable Integer eventId ,@RequestParam("file") MultipartFile file,HttpServletRequest request, HttpServletResponse response){
        /** 上传文件 */
        String dfsPath = fileService.uploadFile(file);
        EmergencyNew emergencyNew = emergencyNewService.getById(eventId);
        if (oConvertUtils.isEmpty(file)){
            return EcpResult.buildUpdateFailed("文件不能为空!");
        }
        if (oConvertUtils.isEmpty(emergencyNew)){
            return EcpResult.buildUpdateFailed("事件不存在,保存文件失败");
        }
        /**  删除冗余文件  */
        if (oConvertUtils.isNotEmpty(emergencyNew.getAnalysis())){
            String analysis = emergencyNew.getAnalysis();
            String[] split = analysis.split("/");
            fileService.deleteFile(split[0], analysis);
        }
        if (oConvertUtils.isEmpty(dfsPath)){
            return EcpResult.failed("保存文件失败");
        }
        User user = CacheUtil.getUser(request);
        if (oConvertUtils.isNotEmpty(user)){
            emergencyNew.setUpdateBy(user.getId()+"");
        }
        emergencyNew.setAnalysis(dfsPath);
        emergencyNew.setUpdateTime(new Date());
        boolean b = emergencyNewService.updateById(emergencyNew);
        if (b){
            String name = file.getOriginalFilename();
            System.out.println(name);
            System.out.println(filePath+name);
            FileUtil.deleteFile(filePath+name);
        }
        return EcpResult.success(dfsPath);
    }

2.文件上传异常

java.io.IOException: recv package size -1 != 10
        at org.csource.fastdfs.ProtoCommon.recvHeader(ProtoCommon.java:206)
        at org.csource.fastdfs.ProtoCommon.recvPackage(ProtoCommon.java:242)
        at org.csource.fastdfs.TrackerClient.getStoreStorage(TrackerClient.java:143)
        at org.csource.fastdfs.StorageClient.newWritableStorageConnection(StorageClient.java:1912)
        at org.csource.fastdfs.StorageClient.do_upload_file(StorageClient.java:702)
        at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:207)
        at org.csource.fastdfs.StorageClient.upload_file(StorageClient.java:225)
        at org.csource.fastdfs.StorageClient1.upload_file1(StorageClient1.java:112)

3.异常情况分析

现象:第一次调用接口文件正常上传,后面再次调用文件上传接口,会一直提示文件上传异常(java.io.IOException: recv package size -1 != 10),将删除方法注释后,文件上传正常。
分析:文件上传和文件删除方法都会建立一次连接(storageClient = new StorageClient(trackerServer, storageServer)),两次建立的连接的对象不是同一个对象,客户端第二次建立连接后,文件服务器会把第一次建立的连接对象剔除掉,后面就会一直出现连接超时的情况。

二、解决方案

1.初始化注入StorageClient对象

代码如下(示例):

	@Autowired
	private StorageClient storageClient;
	@Bean
	public StorageClient getStorageClient(){
		return new StorageClient(trackerServer, storageServer);
	}

2.使用连接池

连接池

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐