【发布时间】:2013-11-27 17:14:38
【问题描述】:
我正在开发 Sinatra 应用程序中的文件上传功能。它小而简单,只需使用 Ruby 的 File 类并手动将临时文件保存到目录即可。我正在尝试使用 Tempfile 实现相同的功能。
我已经上传成功,但现在当我点击链接下载文件时,文件名只是一个数字。它会正确下载和读取文件,但不会保留文件名或文件类型。在我进行更改之前,文件将通过重定向到服务器上新上传的文件的端点在浏览器中打开。我想恢复该功能。
我的代码如下:
post "/positions/:id/attachment" do
html_settings
new_data = post_data
if params[:file_attachment][:file].present?
file = params[:file_attachment][:file]
# file looks like this when uploaded:
#{:filename=>"Screen Shot 2013-11-26 at 4.36.13 PM.png", :type=>"image/png", :name=>"file_attachment[file]", :tempfile=>#<File:/var/folders/85/0kp_g81s1ws16zths3s8d9p80000gn/T/RackMultipart20131127-2757-1kdficq>, :head=>"Content-Disposition: form-data; name=\"file_attachment[file]\"; filename=\"Screen Shot 2013-11-26 at 4.36.13 PM.png\"\r\nContent-Type: image/png\r\n"}
# Tempfile object
temp_file = Tempfile.new(file[:filename], 'uploads') # Create tempfile, save to uploads folder
begin
write_tempfile(file, temp_file)
new_data['file_attachment']['file'] = temp_file
new_data['multipart'] = true
# At this point, the new_data hash looks the same except for a small difference in the path name
# Before tempfile - {"file_attachment"=> {"display_name"=>"test","file"=>#<File:uploads/Screen Shot 2013-11-26 at 11.35.36 AM.png>}, "id"=>"1"}
# With tempfile - {"file_attachment"=> {"display_name"=>"test", "file"=>#<File:/path/to/uploads/Screen Shot 2013-11-26 at 4.36.13 PM.png20131127-2757-eb6w6r>}, "id"=>"1", "multipart"=>true}
response = api_post(attachment_upload_endpoint(params[:id]), new_data)
ensure
delete_tempfile(temp_file)
response
end
end
end
辅助方法:
def write_tempfile(file, temp)
file[:tempfile].rewind # Rewind before reading
temp.write(file[:tempfile].read) # Write to the temp file
temp.rewind # Rewind in order to be read
end
def delete_tempfile(temp_file)
#close! calls #close AND #unlink. #unlink deletes the file
temp_file.close!
end
文件上传后会有https://myserver.com/positions/1/file_attachments/46的链接
现在有谁明白为什么当我点击那个链接时,它会下载文件名为 46 的文件,而不再在浏览器中了?
我还在控制台中收到此通知: 资源解释为 Document,但使用 MIME 类型 binary/octet-stream 传输
谢谢。
【问题讨论】:
-
您是否尝试过使用 Tempfile.new 的数组版本来强制文件扩展名? ruby-doc.org/stdlib-2.0.0/libdoc/tempfile/rdoc/…
-
如果我知道扩展名就可以了。我只是尝试使用 png 并且它有效。但是如果我不知道呢?这是否意味着我必须解析我想要的可能的文件扩展名?
-
我刚刚使用了一些额外的扩展解析。我会进行编辑
标签: ruby sinatra temporary-files