我有一个基于Sinatra的项目与page,用户可以上传MP3文件。
<h2><%= I18n.t(:home_title) %></h2>
<%= I18n.t(:upload_body_text) %>
<form action="/<%= I18n.locale %>/upload" method="post" enctype="multipart/form-data">
<p>
<input type="file" name="song" size="40">
</p>
<div>
<input type="submit" value="<%= I18n.t(:home_submit) %>">
</div>
</form>
上传由这个route处理:
post "/upload" do
File.open('uploads/' + params['song'][:filename], "w") do |f|
f.write(params['song'][:tempfile].read)
end
erb :main
end
文件上传后,它已损坏:
我该如何解决?
您正在以文本模式打开文件(默认值):
File.open('uploads/' + params['song'][:filename], "w")
但你正在写二进制数据(MP3)。您需要在binary mode中打开目标文件:
"b" Binary file mode
Suppresses EOL <-> CRLF conversion on Windows. And
sets external encoding to ASCII-8BIT unless explicitly
specified.
或IO库将尝试将EOL转换为Windows风格的CR-LF对:
File.open('uploads/' + params['song'][:filename], "wb")
# --------------------------------------------------^
此外,您不应使用用户提供的名称(params['song'][:filename]
)作为文件名而不彻底擦洗它;或者更好,不要使用他们的名字,将他们的名字存储在某个地方的数据库中,并使用表格的id
作为文件名。