2009-08-31 45 views
3

我有一个web服务方法,读取一张照片并返回其字节数据。我目前做如下:ruby​​ IO.read()锁吗?

@photo_bytes = IO.read("/path/to/file") 
send_data(@photo_bytes, :filename => "filename", :type => "filetype", :disposition => "inline") 

调用这个了很多,当我收到一些奇怪的行为......偶尔SEND_DATA被返回null。我在想如果一个文件还没有关闭,也许我正在读竞争。使用IO.read打开文件后,是否需要显式关闭文件?我如何使用read_nonblock来做到这一点,它会值得吗?

UPDATE:

所以我做了一些更多的记录和偶尔IO.read就像是1800个字节返回一个值时,它通常返回〜用于图片5800个字节。当它返回1800字节时,图片不会显示在客户端上。当两个用户调用Web服务时,这种情况发生得相当随机。

感谢

汤姆

回答

4

IO.read方法没有做任何咨询文件锁定,所以不应该由其他并发读者的影响。但是,如果您的应用程序的其他地方有写入相同路径的代码,则需要确保以原子方式更新文件。以write(而不是append)模式打开文件会立即将文件截断为零字节,因此,在写入新版本之前,您可以很清楚地看到上述代码片段生成的空响应。

假设你是在* NIX平台,如Linux或OS X,不过,你可以使用原子像这样的代码更新文件:

require 'tempfile' 
require 'fileutils' 

def safe_write(path, data) 
    tmp = Tempfile.new 
    tmp.write(data) 
    tmp.close 
    FileUtils.mv(tmp.path, path) 
end 

这将数据写入到一个临时文件,然后将它以原子方式到"/path/to/file"的位置,没有读者看到零长度的截断版本。

+0

一旦给定的文件被写入,它将永远不会被更新。这是个人资料照片系统。用户上传照片,它由多个用户多次检索。如果用户上传新照片,则会创建一个新文件。当我有很多用户点击该网站时,似乎send_data偶尔会发送空值。 – cakeforcerberus 2009-09-01 00:16:10

+0

而“很多”我的意思是两个。 :) – cakeforcerberus 2009-09-01 00:16:46

+0

哦,另外,我还用<%image_tag filename%>提取数据 - 是否锁定文件? – cakeforcerberus 2009-09-01 00:18:50