通过url下载文件和本地路径下载文件是不一样的!

HTTP下载文件与本地文件下载示例
该博客展示了两种下载文件的方法:一种是从URL直接下载,使用`FileUtils.copyURLToFile`复制文件;另一种是下载本地文件,通过`FileInputStream`和`OutputStream`读写文件流。代码中设置了响应头以实现附件下载,并处理了异常和资源关闭。

通过url下载文件:

    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public void getRequest(HttpServletResponse response) {
        String requestPath = "http://xxx.com/demo/sys/test.pdf"
        String filename = "test.pdf";
        InputStream inputStream = null;
        OutputStream out = null;
        File file = null;
        try {
            file = new File(filename);
            URL url =new URL(requestPath);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
//			conn.setConnectTimeout(1000);//超时提示1秒=1000毫秒
            FileUtils.copyURLToFile(url, file);
//			inputStream =  conn.getInputStream();//获取输出流
            response.setHeader("Content-Disposition", "attachment" + ";filename=\"" + URLEncoder.encode(filename, "UTF-8") + "\"");
            byte[] bytes = new byte[(int)file.length()];
            inputStream = new FileInputStream(file);
            out = response.getOutputStream();
            out.write(bytes, 0, inputStream.read(bytes));
        } catch (Exception e) {
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (file != null && file.exists()) {
                file.delete();
            }
        }
    }

下载本地文件:

@RequestMapping(value = "download",method = RequestMethod.GET)
    public ResponseEntity<byte[]> download(HttpServletResponse response, HttpServletRequest request) throws Exception{

        //预下载文件路径******
        String preDownload_path = "C:/Users/Administrator/Desktop/Learn/pdf/temp8.pdf";
        int index = preDownload_path.lastIndexOf("/");
        //下载后的文件名
        String downloadName = preDownload_path.substring(index+1);
        System.out.println(index);
        System.out.println(downloadName);

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;fileName="+java.net.URLEncoder.encode(downloadName,"UTF-8"));

        FileInputStream is = null;
        OutputStream os = null;
        try {
            URL url = new URL(preDownload_path);
            is = new FileInputStream(String.valueOf(url.openStream()));
//            is = new FileInputStream(new File(preDownload_path));
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int length;
            while ((length = is.read(b)) > 0) {
                os.write(b, 0, length);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            os.close();
            is.close();
        }
        return null;
    }

### **S3 的访问方式:路径 vs. 对象键(Key)** **AWS S3 本质上是一个对象存储(Object Storage),而是传统的文件系统(如HDFS、本地磁盘)**,但它通过 **对象键(Key)** 模拟了类似路径的访问方式。以下是详细解析: --- ## **1. S3 的存储结构** | **概念** | **说明** | |-------------------|-------------------------------------------------------------------------| | **Bucket(存储桶)** | 相当于顶级目录,全局唯一(如 `my-bucket`)。 | | **Key(对象键)** | 类似文件路径(如 `images/2023/photo.jpg`),但本质上是对象的唯一标识符。 | | **Object(对象)** | 存储的实际数据(文件内容)+ 元数据(如大小、类型、最后修改时间)。 | **示例:** - 文件 `report.pdf` 存储在 `documents/2023/` 下: - **Key** = `documents/2023/report.pdf` - **完整访问路径** = `s3://my-bucket/documents/2023/report.pdf` --- ## **2. S3 的访问方式** ### **(1) 通过路径风格的 URL 访问** - **虚拟托管类型(推荐)** ```bash https://my-bucket.s3.amazonaws.com/documents/2023/report.pdf ``` - **路径类型(旧版)** ```bash https://s3.amazonaws.com/my-bucket/documents/2023/report.pdf ``` ### **(2) 通过 AWS CLI/SDK 访问** ```bash # 下载文件 aws s3 cp s3://my-bucket/documents/2023/report.pdf ./local-path/ # 上传文件 aws s3 cp ./local-file.txt s3://my-bucket/path/to/destination/ ``` ### **(3) 通过 API 直接操作对象** ```python import boto3 s3 = boto3.client('s3') # 下载对象 s3.download_file('my-bucket', 'documents/2023/report.pdf', 'local_report.pdf') # 上传对象 s3.upload_file('local_file.txt', 'my-bucket', 'path/in/s3/file.txt') ``` --- ## **3. S3 与文件系统的关键区别** | **特性** | **S3(对象存储)** | **文件系统(如HDFS/NFS)** | |------------------------|---------------------------------------|------------------------------------| | **数据模型** | 扁平结构(Key-Value 存储) | 层级目录树 | | **修改操作** | 对象可修改,只能覆盖或删除 | 支持原地修改文件内容 | | **访问延迟** | 较高(毫秒级,适合高频随机读写) | 较低(适合频繁读写) | | **一致性模型** | 最终一致性(新对象立即可见) | 强一致性(写入后立即可读) | | **存储规模** | 无限扩展 | 受集群规模限制 | --- ## **4. 为什么 S3 用 Key 模拟路径?** - **兼容性**:让用户以熟悉的“目录”方式组织数据。 - **灵活性**:Key 可以包含 `/`,但 S3 内部并无真正的目录结构(只是逻辑划分)。 - **管理便捷**: - 可通过 **AWS 控制台** 可视化查看“文件夹”。 - 支持按前缀(Prefix)搜索,如 `aws s3 ls s3://my-bucket/documents/`。 --- ## **5. 实际应用示例** ### **(1) 存储下载文件** ```bash # 上传本地文件到 S3(自动创建“路径”) aws s3 cp /home/user/data.log s3://my-bucket/logs/2023-10-01/data.log # 下载文件本地 aws s3 cp s3://my-bucket/logs/2023-10-01/data.log ./downloaded.log ``` ### **(2) 批量操作(如同步目录)** ```bash # 同步本地目录到 S3(增量更新) aws s3 sync ./local-folder/ s3://my-bucket/remote-folder/ ``` ### **(3) 通过 HTTP 直接访问文件** 若对象权限为 **public-read**,可直接用 URL 下载: ``` https://my-bucket.s3.amazonaws.com/logs/2023-10-01/data.log ``` --- ## **6. 常见问题解答** ### **Q1: S3 是否有真正的“文件夹”?** - **没有**。S3 仅通过 Key 中的 `/` 模拟目录,控制台显示的“文件夹”仅是可视化效果。 - 空“文件夹”会占用存储空间(除非显式创建占位对象,如 `logs/2023/`)。 ### **Q2: 如何列出某个“目录”下的所有文件?** ```bash aws s3 ls s3://my-bucket/logs/2023-10-01/ --recursive ``` ### **Q3: S3 能否像数据库一样随机读写文件的一部分?** - **能**。S3 对象必须整体上传/下载(但可通过 **Range GET** 读取部分内容)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值