用 Redmine 管理项目,是 Ruby 写的, Ruby 貌似在 Windows 下处理中文编码有点问题,导致 Redmine 中一些中文文件名的图片显示不正常,我找到解决方法但是不懂 Ruby ,请求帮忙。
需求很简单,下面这个函数是对字符串进行处理,处理后的字符串差不多是这样: /attachments/download/455/02%E5%AE.jpg 我想把最后一个“/”后面的字符删除,就是返回是 /attachments/download/455/ 应该很简单吧,函数如下:
def htmlesc( str, mode=:Quotes )
if str
str.gsub!( '&', '&' )
str.gsub!( '"', '"' ) if mode != :NoQuotes
str.gsub!( "'", ''' ) if mode == :Quotes
str.gsub!( '<', '<')
str.gsub!( '>', '>')
end
str
end
1
wadezhao OP 哦,忘记说谢谢了。
谢谢。 |
2
awolfly9 2016-12-08 17:23:18 +08:00
用 / 分割字符串,然后去掉最后一个再把所有的子串连接,就是你想要的
|
3
liprais 2016-12-08 17:23:45 +08:00
str.split("/")[1..-2].join('') 这样?
|
5
liprais 2016-12-08 17:25:07 +08:00 1
@liprais "/attachments/download/455/02%E5%AE.jpg".split("/")[0..-2].join("/")
这下感觉对了,最近真是手酸..... |
8
lightening 2016-12-08 17:33:05 +08:00 1
更推荐用自带的 helper 。
> File.dirname('/attachments/download/455/02%E5%AE.jpg') => # "/attachments/download/455" 如果想加 "/" 就 > File.dirname('/attachments/download/455/02%E5%AE.jpg') + "/" |
9
Jodal 2016-12-08 18:09:24 +08:00 1
|
10
Jodal 2016-12-08 18:11:54 +08:00
最好还是使用 File 的方法,因为文件名有可能空格之类的,虽然我写的正则包含了 233 (笑
|
11
wadezhao OP @liprais 谢谢,不过我完全不懂 Ruby ,是把函数最后一行
str 换成 str.split("/")[0..-2].join("/") 么?貌似不行。 @lightening 谢谢。见上,我把 str 换成 File.dirname(str)+ "/" 貌似不行…… @Jodal 你这个我就完全看不懂了………… |
12
wadezhao OP @liprais
@lightening 还有一个可能,你们两个的方法都对,但是返回的字符串在别的地方还有处理,识别出了尾部不是图片扩展名,又对字符串做了一些操作,导致最终显示在页面里的内容不对,郁闷了,我这个完全不懂 Ruby 的人还得继续去摸索…… |
13
lightening 2016-12-08 20:26:06 +08:00
那你慢慢说,导致的不正常是怎么产生的。原来的图片 url 变成了什么?
|
14
102400 2016-12-08 22:05:23 +08:00 1
"#{File.dirname('/attachments/download/455/02%E5%AE.jpg')}/"
|
15
wadezhao OP @lightening
嗯,谢谢。 是这样,原始的代码,最终体现到页面上,是这样的: <img src="/attachments/download/455/02%E5%AE.jpg"> 但是这张图片并不显示,如果你直接点击这个图片,会提示一段 HTML 代码,说这个文件不存在,而不存的文件名,并不是"02%E5%AE.jpg",而是一个“乱码.jpg ”,换句话说,直接点击,会告诉你 http://URL/attachments/download/455/乱码乱码乱码.jpg 不存在 看上去,像是 Windows 下的 Ruby ,或者是源代码,对中文文件名的处理有一点问题。 所以我就寻找解决方案,最彻底的方案当然是找到乱码的原因,不过这个不好找,我找了一个妥协的方案,那就是,我发现其实直接把文件名去掉的话,是能显示的,就是说 <img src="/attachments/download/455/"> 是可以正常显示的。所以我就想,只要能找到生成这一段代码的 Ruby 源码,生成的字符串,将最后一个“/”之后的字符全删掉,不就行了么? 于是我就找到了这一部分,这一部分的源码是这样的: def inline_textile_image( text ) text.gsub!( IMAGE_RE ) do |m| stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8] htmlesc title atts = pba( atts ) atts = " src=\"#{ htmlesc url.dup }\"#{ atts }" atts << " title=\"#{ title }\"" if title atts << " alt=\"#{ title }\"" # size = @getimagesize($url); # if($size) $atts.= " $size[3]"; href, alt_title = check_refs( href ) if href url, url_title = check_refs( url ) out = '' out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href out << "<img#{ shelve( atts ) } />" out << "</a>#{ href_a1 }#{ href_a2 }" if href if algn algn = h_align( algn ) if stln == "<p>" out = "<p style=\"float:#{ algn }\">#{ out }" else out = "#{ stln }<div style=\"float:#{ algn }\">#{ out }</div>" end else out = stln + out end out end end 虽然我不懂 Ruby ,不过看上去,这一行就是关键: atts = " src=\"#{ htmlesc url.dup }\"#{ atts }" 看起来,生成<img>的“ src ”内容的,就是这一句,而这个 htmlesc 显然是一个函数,用于处理 URL.DUP 这个变量(这个我并不知道是什么,看字面意思似乎是将 URL 变量复制了一份?) 于是就有了我上面的问题,我找到了最初对 htmlesc 这个函数的定义,希望通过修改它来达到我的目的。 但奇怪的是,修改后,并没有如我想象的写回 <img src="/attachments/download/455/"> 写回的是 <img src=""> 所以我猜测,也许后面对输出的字符串还是做了什么修改,高度怀疑这几句: out = '' out << "<a#{ shelve( " href=\"#{ href }\"" ) }>" if href out << "<img#{ shelve( atts ) } />" out << "</a>#{ href_a1 }#{ href_a2 }" if href 但是这个语法我就看不太懂了…………现在就卡在这里了……………… |
16
zhs227 2016-12-08 23:12:49 +08:00
把 shelve 贴出来看看
|
17
doun 2016-12-08 23:32:41 +08:00 via Android
我们也用 redmine ,没有遇到楼主说的问题啊!干嘛要用自己没什么概念的语言做的工具
|
18
doun 2016-12-08 23:36:08 +08:00 via Android
htmlesc 是做类似 html safe 的动作,肯定很多调用的,不要改这个函数,有问题的话,直接加在这个地方好点
|
19
wadezhao OP 奇怪,函数最后一行的
str 我改成 File.dirname('/attachments/download/455/02%E5%AE.jpg') 可以正常输出 /attachments/download/455 但是如果改成 File.dirname(str) 输出就成空字符串了,百思不得其解……………… |
20
wadezhao OP @zhs227 我直接把 shelve 删掉了,这一行改成
out << "<img#{ atts } />" 输出没区别。而且看 19 楼我的新发现,应该还是这个 htmlesc 函数的问题 @doun 是的,实际我是又做了一个 htmlesc_img 函数,只在这个地方用 htmlesc_img 函数。上面一直没说,只是方便讨论。 redmine 在 Linux 下没问题,我在 Windows 上用 Bitnami 现成的安装包,根本不需要懂 Ruby ,很容易就部署,但就是有这个中文文件名的问题,我看网上很多人说,而且最新版的 Redmine 一样有这个问题,应该是 Ruby 或者 Windows 的问题。 我用的是工具,是 Redmine ,不是 Ruby ,如果没这个 Bug , Redmine 是很好的一个工具。 |
21
doun 2016-12-08 23:49:05 +08:00 via Android
贴一下你的函数?
|
22
zhs227 2016-12-08 23:50:24 +08:00
你在不同的地方加一点输出,分段查看一下 url 的值。
|
23
lightening 2016-12-08 23:51:34 +08:00
这个 htmlesc 还用来出来 title ,见 `htmlesc title`。而且是直接改输入的,不依赖返回值。建议你还是不用动这个方法了。
`atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"` 改成 `atts = " src=\"#{ File.dirname(htmlesc(url.dup)) }\"#{ atts }"` |
24
liuhaotian 2016-12-09 08:15:42 +08:00 via iPhone
我觉得这个有点像是被 URLENCODE 了
是不是那个 method 出了问题 |
25
wadezhao OP @lightening 这个方法我试过了,返回的是空(或者是'./'),很奇怪吧
|
26
wadezhao OP @doun
@zhs227 @lightening @liuhaotian 现在最奇怪的,是这样的。首先,我又做了一个函数: def htmlesc_img( str, mode=:Quotes ) if str str.gsub!( '&', '&' ) str.gsub!( '"', '"' ) if mode != :NoQuotes str.gsub!( "'", ''' ) if mode == :Quotes str.gsub!( '<', '<') str.gsub!( '>', '>') end str #这个地方我叫 [A 行] end 然后把程序中这一句: atts = " src=\"#{ htmlesc url.dup }\"#{ atts }" 改成 atts = " src=\"#{ htmlesc_img url.dup }\"#{ atts }" #这一行我叫 [B 行] 现在最诡异的情况在于: 1 ,如果 B 行我不改动,或者说 htmlesc_img 的代码和 htmlesc 完全相同,或者干脆把 htmlesc_img 这个处理函数去掉,则会返回 /attachments/download/455/02%E5%AE.jpg 说明: url.dup 这个变量是有值的,值是待处理的正常值 2 ,如果我把 A 行改为: File.dirname('/attachments/download/455/02%E5%AE.jpg'),可以正常输出 /attachments/download/455 这说明: atts 这个变量后续并没有被再处理,并且 File.dirname 这个函数执行的结果也是正常的 3 , A 行如果改成 v_temp = '' v_temp = v_temp+ File.dirname(str) 或者 v_temp = File.dirname(str) 或者 File.dirname(str) 则返回的字符串是 . (就是一个点儿) A 行如果改成 str.split("/")[0..-2].join("/") 则干脆返回一共空字符串 也就是说,无论我怎么改,也没办法在 htmlesc_img 这个函数内,把 str 这个变量处理,让这个函数返回正确的内容,这太诡异了………… |
27
zhs227 2016-12-09 12:25:09 +08:00 1
直接用 log 吧,观察输出可能不靠谱。我测试过你这个函数一定是没有任何问题的
irb(main):001:0> def htmlesc_img( str, mode=:Quotes ) irb(main):002:1> if str irb(main):003:2> str.gsub!( '&', '&' ) irb(main):004:2> str.gsub!( '"', '"' ) if mode != :NoQuotes irb(main):005:2> str.gsub!( "'", ''' ) if mode == :Quotes irb(main):006:2> str.gsub!( '<', '<') irb(main):007:2> str.gsub!( '>', '>') irb(main):008:2> end irb(main):009:1> File.dirname(str) irb(main):010:1> end => :htmlesc_img irb(main):011:0> htmlesc_img '/attachments/download/455/02%E5%AE.jpg' => "/attachments/download/455" 用日志或写文件方式,逐行记录,不可能这么诡异的 |
28
wadezhao OP |
29
wadezhao OP 我找到原因了,写回页面的代码应该在别的地方还有处理,一言难尽,但我知道大概问题在哪里了,也知道各位告诉我的 File.dirname 这个函数是可用的。
多谢各位,我继续解决问题了。 :) |
30
wadezhao OP 解决了,原来 url 这个变量的值,就是'02%E5%AE.jpg',把前面的‘\attachments\download\455\’加上去,另有其他地方处理。
在 application_helper.rb 里有一个函数: parse_inline_attachments ,是在这里解析最终输出的字符串,其中解析图片 URL 的一行是这样的: "src=\"#{image_url}\"#{alt}" 如楼上各位指点,这一行改成 "src=\"#{File.dirname(image_url)}\"#{alt}" 就达到我的目的了。 |