gpt4 book ai didi

ruby-on-rails - 在 ruby​​/rails 中创建线程安全的非删除唯一文件名

转载 作者:数据小太阳 更新时间:2023-10-29 08:37:47 24 4
gpt4 key购买 nike

我正在构建一个批量文件 uploader 。多个文件在单个请求中上传,我的 UI 提供进度和成功/失败。然后,一旦所有文件都完成,最终请求将处理/完成它们。为此,我需要创建许多比单个请求生命周期更长的临时文件。当然,我还需要保证文件名在应用程序实例中是唯一的。

通常我会使用 Tempfile用于简单的唯一文件名,但在这种情况下它不起作用,因为文件需要保留直到另一个请求进入以进一步处理它们。 Tempfile 在文件关闭和垃圾收集时自动取消链接。

一个较早的问题 here建议使用 Dir::Tmpname.make_tmpname 但这似乎没有记录,我看不出它是如何线程/多进程安全的。保证是这样吗?

在 c 中,我将打开文件 O_EXCL,如果该文件存在,它将失败。然后我可以继续尝试,直到我成功获得一个具有真正唯一名称的文件的句柄。但是 ruby​​ 的 File.open 似乎没有任何类型的“排他性”选项。如果我打开的文件已经存在,我必须附加到它,在最后打开以写入,或者清空它。

在 ruby​​ 中是否有“正确”的方法来做到这一点?

我想出了一个我认为安全但似乎过于复杂的方法:

# make a unique filename
time = Time.now
filename = "#{time.to_i}-#{sprintf('%06d', time.usec)}"

# make tempfiles (this is gauranteed to find a unique creatable name)
data_file = Tempfile.new(["upload", ".data"], UPLOAD_BASE)

# but the file will be deleted automatically, which we don't want, so now link it in a stable location
count = 1
loop do
begin
# File.link will raise an exception if the destination path exists
File.link(data_file.path, File.join(UPLOAD_BASE, "#{filename}-#{count}.data"))
# so here we know we created a file successfully and nobody else will take it
break
rescue Errno::EEXIST
count += 1
end
end

# now unlink the original tempfiles (they're still writeable until they're closed)
data_file.unlink

# ... write to data_file and close it ...

注意:这不适用于 Windows。对我来说不是问题,但读者要小心。

在我的测试中,它工作可靠。但是,还有更直接的方法吗?

最佳答案

我会使用 SecureRandom .

也许是这样的:

p SecureRandom.uuid #=> "2d931510-d99f-494a-8c67-87feb05e1594"

p SecureRandom.hex #=> "eb693ec8252cd630102fd0d0fb7c3485"

您可以指定长度,并指望 almost impossibly small chance of collision .

关于ruby-on-rails - 在 ruby​​/rails 中创建线程安全的非删除唯一文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25345627/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com