Rails应用中PDF上传成功却无法下载的问题求助
问题
在Rails应用中遇到了一个奇怪的问题:通过API上传PDF文件,文件通过has_one_attached :file关联到Document对象,对应的create方法代码如下:
def create if can? :create, Document @document = Document.new(document_params.except(:upload_files)) if document_params[:upload_files].present? uploaded_file = document_params[:upload_files].first @document.file_name = uploaded_file.original_filename @document.file_size = uploaded_file.size.to_s @document.file_type = uploaded_file.content_type @document.file.attach(io: uploaded_file.tempfile, filename: uploaded_file.original_filename, content_type: "application/pdf", identify: false).save end if @document.save redirect_to document_path(@organization, id: @document.id), notice: "Document successfully saved." else redirect_to root_path, alert: "Document could not be saved." end else raise CanCan::AccessDenied end end
在控制台执行doc.file.attached?返回true,数据库中也能查到文件关联记录。但调用Download API生成下载链接后,通过AJAX获取链接并触发下载时,浏览器提示‘the file wasn't available on site’,下载的文件为空或不存在。相关Download方法和AJAX代码如下:
def download respond_to do |format| format.json do if @document.file.attached? file_url = rails_blob_url(@document.file, disposition: "attachment", content_type: @document.file_type) render json: { document: { file: file_url } } else render json: { error: "File not found" }, status: :not_found end end format.html { proxy_attachment_file_render(@document.file) } end end
$.ajax({ url: 'path/to/download/api' dataType: 'json', method: 'GET', success: function(response) { console.log(response) if (response.document && response.document.file) { const fileUrl = response.document.file; const link = document.createElement('a'); link.href = fileUrl; document.body.appendChild(link); link.click(); document.body.removeChild(link); } else { alert('File not available for download.'); } }, error: function() { alert('Error fetching the file.');} });
明明文件已成功上传并关联到对象,却无法正常下载,请问哪里操作有误?
排查与解决思路
1. 验证Blob URL的有效性
直接把AJAX返回的fileUrl粘贴到浏览器地址栏访问,看是否能正常下载:
- 若直接访问也失败,说明问题出在Active Storage服务端:
- 本地存储场景:检查
storage目录下是否存在对应文件,且服务器进程有读写权限。 - 云存储场景(如S3):确认存储桶权限允许访问,同时核对Rails的云存储配置是否正确。
- 本地存储场景:检查
2. 移除identify: false参数
上传时设置identify: false会跳过Rails对文件类型的自动检测,可能导致Blob元数据不完整。尝试修改上传代码:
@document.file.attach(io: uploaded_file.tempfile, filename: uploaded_file.original_filename, content_type: uploaded_file.content_type)
3. 修复AJAX的CSRF或跨域问题
- Rails默认启用CSRF保护,AJAX请求需携带CSRF令牌,补充请求头:
$.ajax({ url: 'path/to/download/api', dataType: 'json', method: 'GET', headers: { 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content') }, // 其余代码不变 });
- 若存在跨域场景,需配置CORS规则允许Blob资源的跨域访问。
4. 检查proxy_attachment_file_render方法
该自定义方法可能存在逻辑错误,可暂时替换为Rails内置的文件返回方式测试:
format.html do send_data @document.file.download, filename: @document.file.filename, type: @document.file.content_type, disposition: 'attachment' end
5. 确认参数白名单配置
确保document_params中包含:upload_files,否则文件可能未实际上传:
def document_params params.require(:document).permit(:name, :description, upload_files: []) end
内容的提问来源于stack exchange,提问作者JCMcRae
相关产品推荐
相关产品推荐

