我有用户条目作为文件名。当然这不是一个好主意,所以我想放弃除[a-z]
,[A-Z]
,[0-9]
,_
和-
之外的所有内容。
例如:
my§document$is°° very&interesting___thisIs%nice445.doc.pdf
应该成为
my_document_is_____very_interesting___thisIs_nice445_doc.pdf
然后理想
my_document_is_very_interesting_thisIs_nice445_doc.pdf
这样做是否有一种优雅而优雅的方式?
答案 0 :(得分:58)
我想建议一个与旧的解决方案不同的解决方案。请注意,旧版本使用已弃用 returning
。顺便说一下,无论如何特定于Rails ,你没有在你的问题中明确提到Rails(仅作为标签)。此外,现有解决方案无法按照您的要求将.doc.pdf
编码为_doc.pdf
。当然,它不会将下划线合并为一个。
这是我的解决方案:
def sanitize_filename(filename)
# Split the name when finding a period which is preceded by some
# character, and is followed by some character other than a period,
# if there is no following period that is followed by something
# other than a period (yeah, confusing, I know)
fn = filename.split /(?<=.)\.(?=[^.])(?!.*\.[^.])/m
# We now have one or two parts (depending on whether we could find
# a suitable period). For each of these parts, replace any unwanted
# sequence of characters with an underscore
fn.map! { |s| s.gsub /[^a-z0-9\-]+/i, '_' }
# Finally, join the parts with a period and return the result
return fn.join '.'
end
您尚未指定有关转化的所有详细信息。因此,我做了以下假设:
A
- Z
,a
- z
,0
- 9
和-
之外的任何字符序列都应该被折叠成单个_
(即下划线本身被视为不允许的字符,字符串'$%__°#'
将变为'_'
- 而不是来自'___'
的部分'$%'
}},'__'
和'°#'
)复杂的部分是将文件名拆分为主要部分和扩展名。在正则表达式的帮助下,我正在搜索最后一个句点,其后是句点之外的其他句号,因此在字符串中没有匹配相同条件的后续句点。但是,必须先加上一些字符,以确保它不是字符串中的第一个字符。
测试功能的结果:
1.9.3p125 :006 > sanitize_filename 'my§document$is°° very&interesting___thisIs%nice445.doc.pdf'
=> "my_document_is_very_interesting_thisIs_nice445_doc.pdf"
我认为是你要求的。我希望这很好,也很优雅。
答案 1 :(得分:27)
来自http://devblog.muziboo.com/2008/06/17/attachment-fu-sanitize-filename-regex-and-unicode-gotcha/:
def sanitize_filename(filename)
returning filename.strip do |name|
# NOTE: File.basename doesn't work right with Windows paths on Unix
# get only the filename, not the whole path
name.gsub!(/^.*(\\|\/)/, '')
# Strip out the non-ascii character
name.gsub!(/[^0-9A-Za-z.\-]/, '_')
end
end
答案 2 :(得分:17)
如果您使用Rails,您还可以使用String#parameterize。这不是特别适用于此,但您将获得令人满意的结果。
"my§document$is°° very&interesting___thisIs%nice445.doc.pdf".parameterize
答案 3 :(得分:2)
在Rails中,您也许还可以使用ActiveStorage::Filename中的sanitize
:
ActiveStorage::Filename.new("foo:bar.jpg").sanitized # => "foo-bar.jpg"
ActiveStorage::Filename.new("foo/bar.jpg").sanitized # => "foo-bar.jpg"
答案 4 :(得分:2)
如果您的目标只是生成在所有操作系统上使用的“安全”文件名(而不是删除任何和所有非ASCII字符),那么我建议使用zaru gem。它并不能解决原始问题所指定的所有内容,但是生成的文件名应该可以安全使用(并且仍然保持所有文件名安全的Unicode字符不变):
Zaru.sanitize! " what\ēver//wëird:user:înput:"
# => "whatēverwëirduserînput"
Zaru.sanitize! "my§docu*ment$is°° very&interes:ting___thisIs%nice445.doc.pdf"
# => "my§document$is°° very&interesting___thisIs%nice445.doc.pdf"
答案 5 :(得分:0)
对于Rails,我发现自己想要保留任何文件扩展名,但对其余字符使用10*sizeof(int)
:
parameterize
实施细节和想法见来源: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/transliterate.rb
filename = "my§doc$is°° very&itng___thsIs%nie445.doc.pdf"
cleaned = filename.split(".").map(&:parameterize).join(".")
答案 6 :(得分:0)
有一个库可能会有所帮助,特别是如果您有兴趣用ASCII替换奇怪的Unicode字符:unidecode。
irb(main):001:0> require 'unidecoder'
=> true
irb(main):004:0> "Grzegżółka".to_ascii
=> "Grzegzolka"