ssm框架下将文件上传到服务器 +下载到本地

  • Post author:
  • Post category:其他


在制作java项目时,我们会疑惑,如果我们想要把本地的图片或者文档上传到服务器,我们该怎么做呢?为实现这个,应该这样做。

案例如下:

1、使用spring框架实现文件上传到服务器并在本地目录生成的功能,可用在上传图片功能和导入excel功能

2、具体实现流程是前端发送请求后端来处理,前端页面如下,这篇文章主要讲述后端业务处理,适合java有些基础的人学习

请添加图片描述

3、业务逻辑梳理

​ 想要实现文件上传,必须要定义文件上传的路径,这个路径是服务器所在的路径,在服务器中开辟空间,把本地的文件上传,这是总的,下面一条一条代码分析

// 上传文件路径
String filePath = NiuaConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
//将路径进行拼接
fileName = filePath + File.separator + fileName;
//根据路径生成 FileInputStream输入流,前三部是生成上传并在本地生成文件,这一步是读取文件,例如想要读取excel进行操作
FileInputStream inputStream = new FileInputStream(new File(fileName));

首先获取上传路径,使用NiuaConfig.getUploadPath()方法,里面通过读取注解获取 yml 配置文件 ,返回

“profile+upload”

//  String filePath = NiuaConfig.getUploadPath() 方法
    public static String getUploadPath()
    {	
        //返回路径,getProfile()通过注解读取yml文件
        return getProfile() + "upload";  D:\niua\upload
    }


    public static String getProfile()
    {
        return profile;
    }
       

创建读取我配置文件的实体类,通过@ConfigurationProperties(prefix = “配置文件名称”) 注解读取配置文件的属性,获取profile的值,定义profile的get和set方法来设置值和获取

// NiuaConfig 中的getProfile()
@Component
@ConfigurationProperties(prefix = "配置文件名称")
public class NiuaConfig {

    /** 上传路径 */
    private static String profile;


    public static String getProfile()
    {
        return profile;
    }

    public void setProfile(String profile)
    {
        NiuaConfig.profile = profile;
    }

    /**
     * 获取头像上传路径
     */
    public static String getAvatarPath()
    {
        return getProfile() + "avatar";
    }

    /**
     * 获取下载路径
     */
    public static String getDownloadPath()
    {
        return getProfile() + "download/";
    }

    /**
     * 获取上传路径
     */
    public static String getUploadPath()
    {
        return getProfile() + "upload";
    }
}

配置文件属性,在yml配置文件中,写入profile属性,通过注解来读取

请添加图片描述

请添加图片描述

FileUploadUtils.upload(filePath, file)方法将刚才获取的路径和file对象传入

// String fileName = FileUploadUtils.upload(filePath, file);
// baseDir 为绝对路径 , 文件对象file, 这MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION允许上传的格式
    public static final String upload(String baseDir, MultipartFile file) throws IOException
    {
        try
        {
            return upload(baseDir, file, 	MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }


以下代码是 return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION) 中的方法详解,

    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {   //获取名字长度
        int fileNamelength = file.getOriginalFilename().length();
        //判断是数据大小
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        //校验文件类型,file为传来的file对象,allowed为传来的文件类型
        assertAllowed(file, allowedExtension);
        //根据一定规则生成文件名
        String fileName = extractFilename(file);
        //在服务器端生成file对象,在服务器中开辟二进制空间,没有在服务器上,应该先建出来
        File desc = getAbsoluteFile(baseDir, fileName);
        //上传的二进制数据写出本地新建的数据,这一步上传已经成功了
        file.transferTo(desc);
        //生成url,通过url就可以访问文件
//        String pathFileName = getPathFileName(baseDir, fileName);
        return fileName;
    }

assertAllowed(file, allowedExtension) 是文件的校验,包括对文件的大小和类型

请添加图片描述

    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {   //文件大小的校验,文件大小不对抛出异常
        long size = file.getSize();
        if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
        {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }
        //获取 file的original名字,original:初始的
        String fileName = file.getOriginalFilename();
        //获取file对象的extension类型
        String extension = getExtension(file);
        //文件格式校验,判断allowedExtension是否为空,判断file的类型是否是允许的类型
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {	//这些if 和 elseif 都是对类型的判断
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }

    }

String fileName = extractFilename(file)是生成名字,包含时间的名字和类型

    public static final String extractFilename(MultipartFile file)
    {
        //获取后缀名
        String extension = getExtension(file);
        //拼接名字  DateUtils.datePath()获取当前时间 日期路径 即年/月/日 如2018/08/08
        String fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
        return fileName;
    }

其中DateUtils.datePath()为获取当前是时间,并且格式为”yyyy/MM/dd”,这个主要是为了根据时间名字生成目录

,例如目录

请添加图片描述

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

IdUtils.fastUUID()方法是获取随机UUID,UUID可以理解为文件名代码

例如文件名

请添加图片描述

    /**
     * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
     *
     * @return 随机UUID
     */
    public static String fastUUID()
    {
        return UUID.fastUUID().toString();
    }

upload方法中的File desc = getAbsoluteFile(baseDir, fileName)方法,在前面的方法中,我们已经校验文件,生成文件名,现在就要把文件上传到服务器,而这个方法是在服务器中开辟存储空间,挖出一块空间。

    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
    {   //生成File类型数据 根据uploadDir绝对路径 ,和生成的fileName,在服务器弄出来空间
        File desc = new File(uploadDir + File.separator + fileName);
        //判断父级目录是否存在
        if (!desc.getParentFile().exists())
        {
            //如果父级目录不存在,新建
            desc.getParentFile().mkdirs();
        }
        if (!desc.exists())
        {
            //如果文件不存在,建立
            desc.createNewFile();
        }
        return desc;
    }

upload方法中的file.transferTo(desc)方法,前面的方法中,我们已经将空间开辟好了,就等将文件放入,这个方法就是将文件放入。file文件放入 开辟的desc中

void transferTo(File var1) throws IOException, IllegalStateException;

通过上面操作文件的上传已经完成了,可以在定义的 例如 D:\test\upload\2022\05\16 找到服务器生成的文件,路径是D:\test\ 时yml中配置的,upload 是 +“upload”进行拼接的,\2022\05\16是根据获取时间方法 得到的,成功的话会有下面类似的文件,上传少个文件生成多少个文件

请添加图片描述

请添加图片描述



版权声明:本文为PDyee原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。