Java 在上传文件时文件名中含有非法字符,如何去除可能导致问题的字符,并确保文件名长度在限制范围内

在Java中上传文件时,如果文件名中含有非法字符,可能会带来一系列的危害和潜在问题。

  1. 编译错误

    • Java文件名称中的非法字符,如斜杠(/)、反斜杠(\)、冒号(:)、星号(*)、问号(?)、双引号(")、尖括号(<>)、竖线(|)等,会导致编译错误。这些字符在Java文件系统中具有特殊含义,因此不能用于文件名中。
  2. 上传失败

    • 当文件名包含URI中的特殊字符,如井号(#)时,可能会导致上传失败。因为Uri类会对文件路径#号后面的内容进行拆分存放,从而导致文件名被截断或更改。
  3. 安全威胁

    • 文件名中的非法字符可能包含一些危险的字符,如“../”或“..\”,这些字符在文件系统中具有特殊的意义,可能导致文件被保存到预期之外的路径下,从而带来安全风险。
    • 如果文件名中包含非法字符,且系统处理不正确,可能导致系统内部信息泄露。例如,在Windows系统中,如果文件名含有非法字符,可能会出错,如果处理不当就会导致信息泄露。
  4. 文件名解析错误

    • 文件名中的空格或其他特殊字符可能导致文件名解析错误,使得文件无法被正确识别和访问。
  5. 长度限制:

    • 文件名加路径的长度可能受到操作系统的限制。在Windows系统中,文件名的最大长度(包括路径)通常为260个字符(Windows 10, 11的NTFS文件系统支持长达32,767个字符的路径,但实际应用中仍建议遵守较短的限制)。如果文件名或路径长度超过这个限制,可能会导致问题。
  6. 跨平台兼容性问题

    • 不同的操作系统和文件系统对文件名的限制和要求可能不同。因此,如果文件名包含非法字符,可能会导致文件在跨平台传输或访问时出现问题。

解决方法:

下面是我一个简单的例子: 

import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FileNameUtil {

    private static final Pattern INVALID_FILENAME_CHARS = Pattern.compile("[\\\\/:*?\"<>|]");
    private static final int MAX_LENGTH = 255; // 根据文件系统或应用需求设置最大长度
    private static final String REPLACEMENT_CHAR = "_";
    private static final String DEFAULT_FILENAME = default_filename;//如果文件名为空就将文件名设置为该字段

    /**
     * 清理文件名,去除可能导致问题的字符,并确保文件名长度在限制范围内
     *
     * @param originalFilename 原始文件名
     * @return 清理后的文件名
     */
    public static String cleanFileName(String originalFilename) {
        if (originalFilename == null) {
            return DEFAULT_FILENAME;
        }

        // 去除路径遍历字符,替换为下划线
        String sanitizedFilename = originalFilename.replaceAll("\\.\\./", REPLACEMENT_CHAR);

        // 使用正则表达式去除无效的文件名字符
        Matcher matcher = INVALID_FILENAME_CHARS.matcher(sanitizedFilename);
        sanitizedFilename = matcher.replaceAll(REPLACEMENT_CHAR);

        // 去除文件名开头和结尾的无效字符(如点号)
        sanitizedFilename = sanitizedFilename.trim().replaceAll("^\\.*|\\.*$", "");

        // 截取文件名并尝试保留扩展名
        String extension = "";
        int dotIndex = sanitizedFilename.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < sanitizedFilename.length() - 1) { // 确保扩展名至少有一个字符
            extension = sanitizedFilename.substring(dotIndex);
            sanitizedFilename = sanitizedFilename.substring(0, dotIndex);

            // 如果文件名(不含扩展名)和扩展名的总长度超过限制,则截断文件名
            if (sanitizedFilename.length() + extension.length() > MAX_LENGTH) {
                sanitizedFilename = sanitizedFilename.substring(0, MAX_LENGTH - extension.length() - 1);
                // 减去1是为了在文件名和扩展名之间添加一个分隔符
                sanitizedFilename = sanitizedFilename.trim(); // 去除可能的尾随空格
                // 确保至少保留一个字符作为文件名
                if (sanitizedFilename.isEmpty()) {
                    sanitizedFilename = REPLACEMENT_CHAR;
                }
            }
        }

        // 如果文件名长度仍然超过限制(不含扩展名),则直接截断
        if (sanitizedFilename.length() > MAX_LENGTH - extension.length()) {
            sanitizedFilename = sanitizedFilename.substring(0, MAX_LENGTH - extension.length() - 1);
            sanitizedFilename = sanitizedFilename.trim(); // 去除可能的尾随空格
            // 确保至少保留一个字符作为文件名
            if (sanitizedFilename.isEmpty()) {
                sanitizedFilename = REPLACEMENT_CHAR;
            }
        }

        // 添加回扩展名,并确保文件名和扩展名之间有一个点号
        if (!extension.isEmpty()) {
            sanitizedFilename += ".";
        }
        sanitizedFilename += extension;

        // 确保文件名不为空
        if (sanitizedFilename.isEmpty()) {
            sanitizedFilename = DEFAULT_FILENAME;
        }

        return sanitizedFilename;
    }
}

这是我的解决方法,简单的处理了一下文件名

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值