最近在做一个文件上传的子模块,总是出现一个问题,就是远程创建目录失败。

之前还在怀疑路径是否出问题了(我有一个习惯就是:目录的最后一个字符必定为"/"),可经过测试后,仍然无法成功创建目录。

然后跟踪源码,经过一番勘察后,最后调用的就是 FTP 的命令,发现并没有任何其他与路径有关系的。

最后想到了一个问题,ftpuser 是否具有该目录的写权限,最后进入服务器检查:

[[email protected] www]# ll
总用量 0
drwx------ 3 ftpuser ftpuser 17 4月  27 00:51 images
drwxr-xr-x 3 root root 58 6月   5 11:23 sources
drwxr-xr-x 4 root root 25 6月   2 11:04 std

果然是权限的问题,通过以下命令:

[[email protected] www]# chown -R ftpuser:ftpuser sources
[[email protected] www]# chown -R ftpuser:ftpuser std

最终问题解决

[[email protected] 9]# pwd
/home/ftpuser/www/sources/2/9
[[email protected] 9]# ls
5de87e8cca0044f6bfbc5b56a729d71f.cpp

最后上 使用 FTPClient 上传文件 的源码,当然这个源码存在诸多问题,反正我怎么看怎么不爽 ; )

/**
 * Description: 向FTP服务器上传文件
 *
 * @param host
 *            FTP服务器hostname
 * @param port
 *            FTP服务器端口
 * @param username
 *            FTP登录账号
 * @param password
 *            FTP登录密码
 * @param basePath
 *            FTP服务器基础目录
 * @param filePath
 *            FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
 * @param filename
 *            上传到FTP服务器上的文件名
 * @param input
 *            输入流
 * @param type
 *            上传文件类型
 *
 * @return 成功返回true,否则返回false
 *
 * @author JohnNiang
 */
public static boolean uploadFile(String host, int port,
    String username, String password, String basePath,
        String filePath, String filename, InputStream input, int type) {
    boolean result = false;
    FTPClient ftp = new FTPClient();
    try {
        int reply;
        logger.info("开始连接ftp服务器,host: " + host + ", port: " + port);
        ftp.connect(host, port);// 连接FTP服务器
        // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
        logger.info("登录ftp,username: " + username);
        ftp.login(username, password);// 登录
        reply = ftp.getReplyCode();
        logger.info("ftp服务器回应: " + reply);
        if (!FTPReply.isPositiveCompletion(reply)) {
            logger.error("登录失败,正在断开连接");
            ftp.disconnect();
            return result;
        }
        logger.info("登录成功");
        // 切换到上传目录
        logger.debug("正在切换至目录: " + basePath + filePath);
        if (!ftp.changeWorkingDirectory(basePath + filePath)) {
            logger.info(basePath + filePath + "目录不存在,正在创建该目录");
            // 如果目录不存在创建目录
            String[] dirs = filePath.split("/");
            String tempPath = basePath;
            for (String dir : dirs) {
                if (null == dir || "".equals(dir))
                    continue;
                tempPath += dir + "/";
                logger.debug("正在切换至" + tempPath + "目录");
                if (!ftp.changeWorkingDirectory(tempPath)) {
                    logger.info(tempPath + "目录不存在,正在创建该目录");
                    if (!ftp.makeDirectory(tempPath)) {
                        logger.error("创建" + tempPath + "目录失败");
                        return result;
                    } else {
                        logger.debug("创建" + tempPath + "目录成功");
                        logger.debug("正在切换至" + tempPath + "目录");
                        ftp.changeWorkingDirectory(tempPath);
                    }
                }
            }
        }
        logger.debug("设置上传文件类型为: " + type);
        ftp.setFileType(type);
        logger.debug("正在上传" + filename + "文件");
        // 上传文件
        if (!ftp.storeFile(filename, input)) {
            logger.error(filename + "上传失败");
            return result;
        }
        logger.debug("ftp注销中...");
        input.close();
        ftp.logout();
        result = true;
    } catch (IOException e) {
        logger.error("", e);
    } finally {
        if (ftp.isConnected()) {
            try {
                ftp.disconnect();
            } catch (IOException ioe) {
            }
        }
    }
    return result;
}