2010-09-16 27 views
23

Tôi không thể gửi send_file (Model.attachment.path) để hoạt động. Nó không thất bại, thay vào đó, nó sẽ gửi một tập tin kích thước 0 byte cho khách hàng, tên tập tin là chính xác mặc dù.Đường ray gửi 0 byte tệp bằng send_file

Vấn đề này bắt đầu xảy ra sau khi tôi đã làm một sự chuyển đổi lớn từ Rails 2.3.8 để 3.

Đã có rất nhiều những thứ khác diễn ra trong sự chuyển đổi này và tôi sẽ cố gắng hết sức mình đến từng chi tiết tất cả trong số họ .

  1. Thay đổi thay đổi máy chủ/Thay đổi máy chủ. Rackspace RHEL5 Linode Ubuntu 10.04LTS
  2. phiên bản Ruby thay đổi, 1.8.6 -> 1.9.2
  3. Rails phiên bản thay đổi, 2.3.8 -> 3.0.0
  4. httpd nền tảng thay đổi, apache2 -> nginx (Tuy nhiên Tôi đã thử trên apache2 là tốt và nó đã không hoạt động).

Tôi đã di chuyển tệp đính kèm qua ftp vì chúng không phải là một phần của kho lưu trữ git của chúng để chúng được xuất bản thông qua triển khai mũ, thay vào đó điều khiển từ xa ft (RHEL5) đến địa phương (Win7) rồi địa phương (Win7) đến từ xa (Ubuntu10)).

Tôi biết rằng FTPing không giữ quyền truy cập tệp thông qua chuyển khoản, vì vậy những gì tôi cũng đã làm là bắt chước các chmod đã được thấy trên các máy chủ trước của tôi để chúng gần giống nhau. (người dùng/nhóm khác nhau, đặt thành root: root thay cho olduser: olduser).

Đoạn trích yêu cầu tải xuống tệp đính kèm từ nhật ký sản xuất của tôi.

Started GET "/attachments/replies/1410?1277105698" for 218.102.140.205 at 2010-09-16 09:44:31 +0000 
    Processing by AttachmentsController#replies as HTML 
    Parameters: {"1277105698"=>nil, "id"=>"1410"} 
Sent file /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc (0.2ms) 
Completed 200 OK in 78ms 

Mọi thứ đều ổn. Hãy để tôi cũng loại trừ các vấn đề địa phương, tôi đã thử tải xuống qua Chrome trên cả Win7 và Ubuntu (trên Vbox).

Hãy để tôi cũng đảm bảo với bạn rằng đường dẫn thực sự chính xác.

[email protected]:/srv/app/current# tail /srv/app/releases/20100916094249/attachments/replies/UE0003-Requisition_For_Compensation_Leave.doc 
# 
    # 
     %17nw 
       HQ��+1ae���� 
              %33333333333(��QR���HX�"%%��@9 
��@�p4��#[email protected]��Unknown������������G��z �Times New Roman5��Symbol3&� 
         �z �Arial5&� 

Vì vậy, để tổng hợp câu hỏi, làm cách nào để gửi send_file thực sự gửi tệp thay vì rác giả 0 byte giả mạo.

Trả lời

45

send_file:x_sendfile param mặc định là true trong Rails 3. Tính năng này offloads truyền tải đến máy chủ front - Apache (với mod_xsendfile) hoặc lighttpd, bằng cách trả lại phản hồi trống với X-Sendfile tiêu đề với con đường.

Nginx sử dụng X-Accel-Redirect tiêu đề cho cùng một chức năng nhưng bạn phải Rails cấu hình đúng cách trong tập tin môi trường thích hợp:

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' 

Rails 3 cập nhật: dòng này đã tồn tại trong production.rb, chỉ cần bỏ ghi chú nó.

Thêm sendfile on; vào cấu hình nginx của bạn để sử dụng tiêu đề được gửi bởi Rails. Hãy nhớ rằng đường dẫn tuyệt đối phải được sử dụng và nginx phải có quyền truy cập đọc vào tệp.

Một cách khác cho các tập tin aliased:

Để bảo mật tốt hơn tôi sử dụng bí danh trong nginx thay vì đường dẫn tuyệt đối, tuy nhiên send_file phương pháp kiểm tra sự tồn tại của tập tin mà không thành công với bí danh. Vì vậy tôi đã thay đổi hành động của tôi để:

head(
     'X-Accel-Redirect'=> file_item.location, 
     'Content-Type' => file_item.content_type, 
     'Content-Disposition' => "attachment; filename=\"#{file_item.name}\""); 
    render :nothing => true; 
+2

Tôi thực sự phát hiện ra giải pháp ngày hôm qua và viết blog về nó ngày hôm nay http://www.novafist.com/2010/09/send_file-sends-0- byte-to-client-in-rails/ – fivetwentysix

+2

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' thậm chí còn tốt hơn head(). – gertas

+0

Cảm ơn câu trả lời, đã cứu tôi một thời gian! –

18

Trong Rails 3, chỉ cần bỏ ghi chú dòng config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' trong production.rb bên trong các môi trường thư mục.

3

Tôi đã có vấn đề tương tự với send_file() trong quá khứ, bằng cách sử dụng send_data() thay vì lưu lại cho tôi (ví dụ: send_data File.read (tên tệp),: disposition => 'inline',: type => " một số/mimetype ")

+0

cảm ơn bạn vì điều này, tiết kiệm cho tôi rất nhiều thời gian gỡ lỗi vì tôi không muốn nhận xét ra cấu hình. – covard

14

Có, tôi đã gặp vấn đề tương tự với X-sendfile được bật theo mặc định trong Rails 3 quá.

Nếu bạn có khối lượng lớn các cuộc gọi "send_file", bạn chỉ có thể bình luận ra dòng sau đây vào config/môi trường/production.rb:

#config.action_dispatch.x_sendfile_header = "X-Sendfile" 

Sau đó send_file phương pháp bắt đầu làm việc một cách hoàn hảo.

Vì tôi không thể cài đặt phần mở rộng x-sendfile cho Apache, tôi chỉ tìm kiếm một chút và tìm thấy điều này.

Tôi hy vọng điều đó sẽ hữu ích.

+0

Trên một cài đặt apache này xóa vấn đề của tôi ngay lập tức là tốt. Tìm thấy rất tốt –

0

trên đường ray 4, tôi nhận ra sự cố của mình là tôi đã xóa tệp tạm thời mà ive được tạo để gửi cho người dùng.

nếu tôi không xóa tệp, send_file hoạt động. ive không được thử nghiệm trên mỏng nhưng nó hoạt động tốt trên hành khách 5 như máy chủ độc lập

Các vấn đề liên quan