JAVA前端上传文件后端接收文件并保存在本地

前言

在一些情境下,用户通过浏览器上传word、excel、pdf等各种类型的文件到系统,上传后可以随时下载。下载文件可以通过虚拟路径的方式访问虚拟路径通过浏览器下载;也可以后端直接发送文件流给前端完成下载,发送文件到网页并从网页下载文件

上传文件

控制层接口
java 复制代码
 @RequestMapping(value = "/action/upload/new/file/release", method = RequestMethod.POST)
    public EiInfo uploadNewActionFileRelease(MultipartFile[] files) {
        EiInfo eiInfo = new EiInfo();
        ResultMessage resultMessage = service.uploadFile(files[0]);
        return ReturnOutInfo.outInfoSuccess(eiInfo, "上传文件成功");
    }
服务层处理
java 复制代码
	// 文件保存路径写在了yml文件中
    @Value("${file.path.local}")
    private String fileLocalPath;

@Override
    public ResultMessage uploadFile(MultipartFile file) {
        try {
            // 封装文件信息
            FileSaveDTO fileSaveDTO = FileUtil.handleFileSave(fileLocalPath, file);
            return new ResultMessage(1, "文件上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultMessage(-1, e.getMessage());
        }
    }
application.yml配置文件保存路径
yml 复制代码
file:
  path:
    local:
      D:/JavaCode/bao_safety_management_system/bao_safety_platform_system/safe_file/
    # img/
    tomcat:
      http://192.168.0.58:8189/safety-platform/safe/file/
文件工具类 FileUtil

工具类中有保存文件和下载文件两个方法。

java 复制代码
public class FileUtil {

    private static SimpleDateFormat sfFile = new SimpleDateFormat("yyyyMMddHHmmss");

    public static FileSaveDTO handleFileSave(String localPath, MultipartFile file) throws Exception {
        // 处理传来的文件
        String name = file.getOriginalFilename();
        String saveName = "file-" + sfFile.format(new Date()) + UUID.randomUUID().toString().substring(0, 4) + name.substring(name.lastIndexOf("."));
        File saveFile = new File(localPath + saveName);
        file.transferTo(saveFile);

        // 判断文件是否是图片类型
        // Path path = saveFile.toPath();
        // String type = Files.probeContentType(path);
        if (Files.probeContentType(saveFile.toPath()) != null) {
            return new FileSaveDTO(name, saveName, Files.probeContentType(saveFile.toPath()).startsWith("image/"));
        } else {
            return new FileSaveDTO(name, saveName, false);
        }
    }

    public static boolean downloadFile(File file, String fileName, HttpServletResponse response) throws Exception {
        // 清空缓冲区,状态码和响应头(headers)
        response.reset();
        // 设置ContentType,响应内容为二进制数据流,编码为utf-8,此处设定的编码是文件内容的编码
        response.setContentType("application/octet-stream;charset=utf-8");
        // 以(Content-Disposition: attachment; filename="filename.jpg")格式设定默认文件名,设定utf编码,此处的编码是文件名的编码,使能正确显示中文文件名
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "utf-8"));

        // 实现文件下载
        byte[] buffer = new byte[1024 * 1024 * 1024];
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            // 获取字节流
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
文件信息

文件保存在本地后,将文件信息封装到一个对象中返回给调用保存文件功能的方法中,方便下一步操作

java 复制代码
public class FileSaveDTO {
    private String actualName = "";/*文件名字*/
    private String saveName = "";/*保存在本地时文件名*/
    private Boolean isImage = false;/*是否是图片文件*/

    public FileSaveDTO() {
    }

    public FileSaveDTO(String actualName, String saveName, Boolean isImage) {
        this.actualName = actualName;
        this.saveName = saveName;
        this.isImage = isImage;
    }

    public String getActualName() {
        return actualName;
    }

    public void setActualName(String actualName) {
        this.actualName = actualName;
    }

    public String getSaveName() {
        return saveName;
    }

    public void setSaveName(String saveName) {
        this.saveName = saveName;
    }

    public Boolean getImage() {
        return isImage;
    }

    public void setImage(Boolean image) {
        isImage = image;
    }
}

浏览器中使用虚拟路径下载文件

通过如下配置,前端在浏览器中可以通过虚拟路径直接下载文件

复制代码
http://192.168.0.58:8189/safety-platform/safe/file/xxx.docx
java 复制代码
@Configuration
public class WebFileConfig implements WebMvcConfigurer {


    @Value("${file.path.local}")
    private String fileLocalPath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/safe/file/**").addResourceLocations("file:" + fileLocalPath);
    }
}
相关推荐
哭哭啼6 分钟前
JAVA服务问题诊断
java·开发语言·jvm
小灰灰搞电子12 分钟前
Rust+Slint 实现温度计源码分享
前端·rust·slint
计算机魔术师21 分钟前
面壁智能 OpenBMB 推出 MathForm,面向 Lean 4 数学自动形式化的开源框架、数据集与模型
前端
Sayuanni%332 分钟前
SpringBoot 从注解到源码:核心知识点总结
java·spring boot·后端
NeilCarmack1 小时前
Deepseek-harness增加桌面版端序列:第 2 讲 · spawn Electron:当前进程如何“交棒“
前端·javascript·electron
坚定信念,勇往无前1 小时前
Maven 私有仓库-nexus
java
Minner-Scrapy1 小时前
Scrapy 2.17 源码解析:Scheduler 调度器与磁盘/内存双队列
java·爬虫·python·scrapy·网络爬虫·twisted
晚风醉蝶1 小时前
1-11-奇偶排序-OddEvenSort
java·数据结构·算法
上海魁鲸科技有限公司1 小时前
APS高级排产系统到底有什么用?一文讲清功能、选型与落地建议
前端·microsoft·excel
陈随易1 小时前
Bun v1.4 更新总结:把浏览器、图片、定时任务和工程工具都装进一个运行时
前端·后端·程序员