【问题解决】Java下载远程服务器资源到本地,本地提供下载服务,解决中文乱码问题

2023-11-05

Java下载远程服务器资源到本地,本地提供下载服务

1.通过远程访问远程URL获取服务资源

/**
     * 从指定URL下载文件并保存到指定目录
     * @param filePath 文件将要保存的目录
     * @param method 请求方法,包括POST和GET
     * @param name 文件名
     * @param url 请求的路径
     * @return
     */
public static File saveUrlAsFile(String url,String filePath,String method,String name) throws Exception{
    String fileName = name;     //为下载的文件命名
    //创建不同的文件夹目录
    File file=new File(filePath);
    //判断文件夹是否存在
    if (!file.exists())
    {
        //如果文件夹不存在,则创建新的的文件夹
        file.mkdirs();
    }
    FileOutputStream fileOut = null;
    HttpURLConnection conn = null;
    InputStream inputStream = null;
    // 建立链接
    URL httpUrl=new URL(url);
    conn=(HttpURLConnection) httpUrl.openConnection();
    //以Post方式提交表单,默认get方式
    conn.setRequestMethod(method);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    // post方式不能使用缓存
    conn.setUseCaches(false);
    //连接指定的资源
    conn.connect();
    //获取网络输入流
    inputStream=conn.getInputStream();
    BufferedInputStream bis = new BufferedInputStream(inputStream);
    //判断文件的保存路径后面是否以/结尾
    if (!filePath.endsWith("/")) {

        filePath += "/";

    }
    //写入到文件(注意文件保存路径的后面一定要加上文件的名称)
    fileOut = new FileOutputStream(filePath+fileName);
    BufferedOutputStream bos = new BufferedOutputStream(fileOut);

    byte[] buf = new byte[4096];
    int length = bis.read(buf);
    //保存文件
    while(length != -1)
    {
        bos.write(buf, 0, length);
        length = bis.read(buf);
    }
    bos.close();
    bis.close();
    conn.disconnect();
    return file;
}

如此一来远程的服务资源就被成功保存到本地了

2.后台读取本地下载的资源,提供用户下载功能

  • 首先去到之前定义的filePath路径中
    • 不存在:抛出异常
    • 存在:走下载
    • 下载完成后:finally——>循环递归 清除本地资源,释放空间(因为文件File类)
    // 局部代码块
	InputStream inputStream;
    OutputStream outputStream;
    File file1 = new File(filePath);
    try {
        if (file1.exists()){
            response.setContentType(contentType+";charset=utf-8");
            String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
            response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);

            inputStream = new FileInputStream(filePath+"/"+courseName + "/" + fileName);
            outputStream = new BufferedOutputStream(response.getOutputStream());
            byte[] bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1){
                response.getOutputStream().write(bytes,0,len);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        //删除本地文件
        deleteFile(file1);
    }

3.删除本地文件

public static void deleteFile(File file){
    //判断文件不为null或文件目录存在
    if (file == null || !file.exists()){
        System.out.println("文件删除失败,请检查文件路径是否正确");
        return;
    }
    //取得这个目录下的所有子文件对象
    File[] files = file.listFiles();
    //遍历该目录下的文件对象
    for (File f: files){
        //打印文件名
        String name = file.getName();
        //判断子目录是否存在子目录,如果是文件则删除
        if (f.isDirectory()){
            deleteFile(f);
        }else {
            f.delete();
        }
    }
    //删除空文件夹  for循环已经把上一层节点的目录清空。
    file.delete();
}

踩坑总结

在获取服务器资源和后端提供下载的服务的时候都很顺利,但是在下载文件的时候,遇到文件名称带有中文就会出现问题!!

最初版本:

/** 上面代码省略,此处仅显示响应部分 */
response.setContentType(contentType+";charset=UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileName);
/** 下面代码相同,省略 */

这种做法可以正常下载:名字只包含数字和英文的文件,但是在遇到包含中文的文件,中文部分就会不显示并且连后缀都没有咯。

示例:本地要下载的文件名称(java基础语法.doc),点击下载后提示保存的文件名称(java),后缀也就都没有了。虽然说你可以手动把后缀给加上去后正常打开,但是体验感极差,况且,作为一个普通用户,并不知道你原文件的格式具体是什么。。

第二代版本:

尝试了网上的各种也都不行

//例如1
finalFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-disposition", "attachment;filename="+finalFileName);

//例如2
response.setHeader("Content-disposition", "attachment;filename="+URLEncoder.encode(fileName,"UTF8"));

第一次完全没反应= =,带中文名称的文件下载下来和初代版本一样,捞不谈

第二种可以正常下载文件了,并且可以正常打开。但是下载过后文件名称出现乱码

#具体就是这种感觉
java基础语法.doc        ——————————》java%32%512E%152113%12.doc   (大概就是这种感觉)

虽说不影响使用,但是看起来及其难受

最终版本:

String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);

有效解决下载文件中文编码乱码问题。心累啊~

常用文件后缀及其编码枚举类(FileSuffix)

package com.jeesite.modules.study.entity.enums;

public enum FileSuffix {
    DOC("doc", "application/msword"),
    DOCX("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
    XLS("xls", "text/xml"),
    XLSX("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
    PPT("ppt", "application/vnd.ms-powerpoint"),
    PPTX("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
    PDF("pdf", "application/pdf"),
    WPS("wps", "application/vnd.ms-works"),
    TXT("txt", "text/plain"),
    MP4("mp4", "video/mp4");

    FileSuffix(String suffix, String contentType) {
        this.suffix = suffix;
        this.contentType = contentType;
    }

    private String suffix;

    private String contentType;

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public static String getContentType(String suffix) {
        FileSuffix[] values = FileSuffix.values();
        for (FileSuffix item : values) {
            if (item.getSuffix().equals(suffix)) {
                return item.getContentType();
            }
        }
        return null;
    }
}

完整代码

public void downloadOneFile(String id, HttpServletResponse response) throws Exception {
    //指定下载到服务器的地址
    String filePath = "/usr/local/files" + UUID.randomUUID() + "/";
    //查询id对应的文件名称,地址,URL
    Map<String, Object> file = stStudentService.downloadOneFile(id);
    if (file != null) {
        String fileName = file.get("fileName").toString();
        if (file.get("fileName") != null && fileName.length() > 80) {
            fileName = fileName.substring(0, 80);
        }
        String courseName = file.get("courseName").toString();
        if (file.get("courseName") != null && courseName.length() > 80) {
            courseName = courseName.substring(0, 80);
        }
        //文件路径
        String fileUrl = file.get("fileUrl").toString();
        String[] split = fileName.split("\\.");
        //文件后缀
        String suffix = split[split.length - 1];
        //自定义枚举类,匹配 后缀名所对应的contentType
        String contentType = FileSuffix.getContentType(suffix);
		//获取并下载服务器资源到本地
        DownloadFiles.saveUrlAsFile(fileUrl, filePath + "/" + courseName, "GET", fileName);

        //提供本地下载服务
        InputStream inputStream;
        OutputStream outputStream;
        File file1 = new File(filePath);
        try {
            if (file1.exists()){
                response.setContentType(contentType+";charset=utf-8");
                String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
                response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);

                inputStream = new FileInputStream(filePath+"/"+courseName + "/" + fileName);
                outputStream = new BufferedOutputStream(response.getOutputStream());
                byte[] bytes = new byte[1024];
                int len;
                while ((len = inputStream.read(bytes)) != -1){
                    response.getOutputStream().write(bytes,0,len);
                }
                outputStream.flush();
                outputStream.close();
                inputStream.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            //删除本地文件,释放资源
            deleteFile(file1);
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【问题解决】Java下载远程服务器资源到本地,本地提供下载服务,解决中文乱码问题 的相关文章

随机推荐

  • 增量式PID是什么?不知道你就落伍了

    目录 1 什么是增量式PID 2 举个例子 2 1 位置式PID 2 2 增量式PID 3 伪算法 4 C语言实现 5 总结 在之前一篇博客中 简易PID算法的快速扫盲 简单介绍了PID算法的基本原理和位置式算法的实现过程 由于部分推导过程
  • WinNas之seafile server私人云盘搭建

    目录 部署方法 其他说明 部署方法 避免重复造车轮 直接附别人写的链接 https www kingsonho com install seafile on windows 其他说明 安装后如果需要修改web登录端口号 只在web页面上修改
  • JVM中一次完整的GC流程中是怎样的,对象如何晋升到老年代,说说你知道的几种主要的JVM参数

    对象诞生即新生代 gt eden 在进行minor gc过程中 如果依旧存活 移动到from 变成Survivor 进行标记 当一个对象存活默认超过15次都没有被回收掉 就会进入老年代 主要的JVM参数 http ifeve com use
  • 直流减速电机通过编码器计算车轮转速、车轮速度、路程计算。

    第一步 计算Nms间隔的计数变化量 变化量var 当前读数 前次读数 第二步 计算1s间隔的计数变化量 设N 200 变化量var 5 第三步 计算1min间隔编码器的输出脉冲个数 变化量var 5 4 倍频数 第四步 计算1min间隔编码
  • 基于Unity3D的黄金矿工

    1 游戏背景 黄金矿工小游戏 是一款敏捷 经典小游戏 怀揣梦想的黄金矿工为了寻找更多金子开始了他的挖金之旅 游戏目标 使用钩子放入地下 开拓你的智慧寻找宝物 达到目标金额过关吧 2 开发工具的基本使用 本游戏开发工具选择Unity3D 20
  • Matlab yolov2 深度学习物体检测 超级简单代码

    在深度学习的物体检测方面 相比其他平台 MATLAB打包好了很多模块方法和网络 对于简单的应用 已经足够应付 大家跟着调用 稍微修改一下适应的参数就可以啦 下面我手把手教学 1 需要读取提前制作的csv文件 里面有training data
  • [A3C]:算法原理详解

    强化学习 A3C算法原理 深度强化学习框架使用异步梯度下降来优化深度神经网络控制器 提出了四种标准强化学习算法的异步变体 并证明并行actor learners在训练中具有稳定作用 使得四种方法都能成功地训练神经网络控制器 首先明确什么是A
  • 笔试,橘子称重题

    题目 甲有m个橘子分别为n克 每次找到平均数 要么丢弃比它大的 要么丢弃比它小的 将剩下的和记为s 不断循环 要求输入一些数字 其与s比较 有则输出YES 无则输出NO 第一行输入橘子个数与要比较的数字的个数 第二行输入橘子重量 第三行到结
  • 小儿机器人编程基础课

    小儿机器人编程基础课 小孩子的学习从古至今都是家长们十分关心和重视的一件事情 很多的家长在培养孩子的学习方面也可以说是相当的耐心的 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对于小儿机器人编程基础课并不是很清楚 今天我们
  • 【测验1 编程题】: Python基本语法元素 (第1周)

    第一题 Hello World的条件输出 描述 获得用户输入的一个整数 参考该整数值 打印输出 Hello World 要求 如果输入值是0 直接输出 Hello World 如果输入值大于0 以两个字符一行方式输出 Hello World
  • sql server中bit类型在数据库和C#中的表示

    select count 1 from select ROW NUMBER over order by MinuteID as RowId from OA Minutes WHERE 1 1 and DelFlag false as tem
  • BLE 和 Zigbee 肉眼读数(更新ing)

    BLE1M 画相位图 可以读出preamble 01010101 同步码 01101011 通过向下向上的轨迹来肉眼读 原理是需要看如何进行调制的 toolbox中是GMSK调制 所以反着推回去 就知道画相位图能直接肉眼读数了 同理Zigb
  • JTest

    jtest解释 第一章 简介 jtest是parasoft公司推出的一款针对java语言的自动化白盒测试工具 它通过自动实现java的单元测试和代码标准校验 来提高代码的可靠性 Jtest先分析每个java类 然后自动生成junit测试用例
  • 论文精读:FairMOT: On the Fairness of Detection and Re-Identification in MultipleObject Tracking

    1 提出背景 以往的工作通常将re ID视为次要任务 其准确性受到主要检测任务的严重影响 因此 网络偏向于主检测任务 这对re ID任务不公平 2 核心思想 将MOT表示为单个网络中目标检测和reid的多任务学习 因为它允许两个任务的联合优
  • Ubuntu18.04 搭建Hadoop完全分布式环境--踩坑局

    安装Ubuntu18 04 暂时无坑 跟着CSDN教程 坑一 su root 无法切换root用户 提示 Authentication failure 填坑 sudo psswrd 然后当前用户密码 然后输入 root密码 确认 root
  • Linux环境下,通过shell脚本实现一键部署MySQL,并支持多种类型

    Linux环境下一键部署MySQL脚本 支持多种类型 前言 一 使用前须知 二 使用方法 三 shell脚本内容 总结 前言 MySQL是目前最流行的关系型数据库管理系统之一 属于 Oracle 旗下产品 由于它是开源软件 因此很多企业在
  • 业界AI 推理芯片比较

    业界AI 推理芯片比较 公司 创立时间 地点 产品 架构 算力 特色 瀚博半导体 2018年12月 上海 SV02 DSA 200TOPS 手机 12 导管 1
  • 普源示波器 电脑 连接 软件_乐高wedo2.0电脑软件安装及蓝牙连接方法

    先上一段官方视频 wedo2 0的软件下载方法如下 1 ipad端 直接去苹果应用商店下载 2 安卓端 先下载应用宝 再从应用宝里搜索wedo2 0下载安装 3 PC端 https education lego com zh cn down
  • Android:rk3588 kernel单编

    Android12 0不能直接烧写kernel img和resource img Android12 0的kernel img和resource img包含在boot img中 需要使用build sh AK 命令来编译 kernel 编译
  • 【问题解决】Java下载远程服务器资源到本地,本地提供下载服务,解决中文乱码问题

    Java下载远程服务器资源到本地 本地提供下载服务 1 通过远程访问远程URL获取服务资源 从指定URL下载文件并保存到指定目录 param filePath 文件将要保存的目录 param method 请求方法 包括POST和GET p