使用open-uri加载URL生成Tempfile后的处理及相关技术疑问
关于Ruby中Tempfile的几个问题解答
我来逐个解答你遇到的关于Tempfile的问题:
1. 是否有方法可直接从Tempfile对象获取原始文件名?
很遗憾,open-uri返回的Tempfile对象不会自动保存原始文件的名称——它只是把下载的内容存到一个临时文件里,并没有保留URL里的文件名信息。不过你可以自己从原始URL中解析出文件名,用URI.parse配合File.basename就能轻松做到:
require 'open-uri' require 'uri' url = "https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png" file = open(url) original_filename = File.basename(URI.parse(url).path) # 结果就是 "Snip20180323_40.png"
2. Tempfile对象的主要用途是什么?它与普通File对象有何区别?
Tempfile的核心用途
Tempfile是Ruby专门用来创建临时文件的类,主要用来处理那些不需要长期保存的临时数据:比如下载的临时内容、生成的中间计算结果、临时报表等。它最大的优势是不用你手动管理文件的删除——默认情况下,当Tempfile对象被垃圾回收或者程序结束时,对应的临时文件会自动被删除。
和普通File的区别
- 文件名与路径:
Tempfile会自动在系统临时目录(比如Mac的/var/folders/...)生成一个唯一的随机文件名,避免文件冲突;而普通File需要你指定具体的路径和文件名,或者操作已存在的文件。 - 生命周期:
Tempfile默认自动销毁,不用手动调用File.delete;普通File创建后会一直存在,除非你主动删除。 - 权限设置:
Tempfile默认的文件权限更严格(通常是0600,只有当前用户可读可写),更安全;普通File的权限会继承系统默认设置。 - 使用场景:
Tempfile适合临时数据的短期存储,用完即删;普通File适合需要长期保存或者明确路径的文件操作。
3. 能否将Tempfile对象转换为File对象?
完全不需要转换!因为**Tempfile本身就是File类的子类**,你可以直接把它当作普通的File对象来使用。比如你可以调用所有File支持的方法:
file = open("https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png") puts file.is_a?(File) # 输出 true puts file.size # 可以直接获取文件大小 puts file.read # 直接读取文件内容
4. 如何将该Tempfile以原始文件名写入本地目录?
结合前面提到的解析文件名的方法,再配合文件复制或者内容写入的方式就能实现。这里提供两种常用的方法:
方法一:用FileUtils复制临时文件(更高效)
require 'open-uri' require 'uri' require 'fileutils' url = "https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png" file = open(url) original_filename = File.basename(URI.parse(url).path) target_dir = "/users/user_name/images" target_path = "#{target_dir}/#{original_filename}" # 先确保目标目录存在(如果不存在就创建) FileUtils.mkdir_p(target_dir) # 复制临时文件到目标路径 FileUtils.copy_file(file.path, target_path)
方法二:读取临时文件内容写入新文件
如果不想依赖FileUtils,也可以手动读取内容写入:
require 'open-uri' require 'uri' url = "https://s3-ap-southeast-1.amazonaws.com/xxx/Snip20180323_40.png" file = open(url) original_filename = File.basename(URI.parse(url).path) target_dir = "/users/user_name/images" target_path = "#{target_dir}/#{original_filename}" # 创建目标目录 Dir.mkdir(target_dir) unless Dir.exist?(target_dir) # 写入内容 File.open(target_path, 'wb') do |f| f.write(file.read) end
注意:操作完成前尽量不要关闭Tempfile对象,因为有些系统会在关闭后立即删除临时文件。
内容的提问来源于stack exchange,提问作者Xullnn
相关产品推荐
相关产品推荐

