2012-05-08 25 views
19

Tôi tìm nạp hình ảnh với mở-uri từ một trang web từ xa và lưu giữ chúng trên máy chủ cục bộ của tôi trong ứng dụng Ruby on Rails của tôi. Hầu hết các hình ảnh được hiển thị mà không có sự cố, nhưng một số hình ảnh không hiển thị.Tại sao OpenURI xử lý các tệp có dung lượng dưới 10kb như StringIO?

Sau một gỡ lỗi phiên rất dài cuối cùng tôi phát hiện ra (nhờ this blogpost) rằng lý do cho điều này là các class Buffer trong các tập tin open-uri-libary xử lý với ít hơn 10KB trong kích thước như IO-đối tượng thay vì tempfiles.

tôi quản lý để có được xung quanh vấn đề này bằng cách làm theo các câu trả lời từ Micah Winkelspecht để this StackOverflow question, nơi tôi đặt đoạn mã sau trong một tập tin trong initializers tôi:

require 'open-uri' 
# Don't allow downloaded files to be created as StringIO. Force a tempfile to be created. 
OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax') 
OpenURI::Buffer.const_set 'StringMax', 0 

này hoạt động như mong đợi cho đến nay, nhưng tôi hãy tự hỏi, tại sao họ đặt mã này vào thư viện ngay từ đầu? Có ai biết một lý do cụ thể, tại sao các tệp có kích thước dưới 10kb được coi là StringIO không?

Vì mã trên thực tế đặt lại hành vi này trên toàn cầu cho toàn bộ ứng dụng của tôi, tôi chỉ muốn đảm bảo rằng tôi không phá vỡ bất kỳ thứ gì khác.

Trả lời

12

Khi lập trình mạng, bạn phân bổ bộ đệm có kích thước lớn hợp lý và gửi và đọc các đơn vị dữ liệu phù hợp với bộ đệm. Tuy nhiên, khi xử lý các tệp (hoặc đôi khi được gọi là BLOB), bạn không thể giả định rằng dữ liệu sẽ phù hợp với bộ đệm của bạn. Vì vậy, bạn cần xử lý đặc biệt cho các luồng dữ liệu lớn này. Tuy nhiên, các gói dữ liệu thực sự là một lớp 4, giống như các khung ở lớp 2. Vì điều này đang xảy ra một lớp 7, chúng có thể được gọi là các thông điệp tốt hơn. .)

Đối với thư trả lời lớn hơn 10K, thư viện open-uri đang thiết lập thêm phí để ghi vào đối tượng luồng. Khi theo kích thước StringMax, nó chỉ bao gồm chuỗi trong thư, vì nó biết nó có thể vừa với bộ đệm.

+0

cảm ơn, lời giải thích tốt đẹp – klaffenboeck

+3

Không hoàn toàn chính xác. Chuỗi được sử dụng làm bộ đệm trong trường hợp này không có kích thước cố định; chuỗi trong Ruby được tự động thay đổi kích cỡ. Thật vậy, bạn có thể tự động thay đổi kích thước bộ đệm trong hầu hết các ngôn ngữ (mặc dù không phải lúc nào cũng tự động). Tôi nghi ngờ lý do thực sự để sử dụng StringIO cho các tập tin nhỏ là một hiệu suất sử dụng/bộ nhớ thương mại-off. – pelle

+2

True @pelle. Lưu ý rằng bạn nói không hoàn toàn. Trong trường hợp BLOB, * bất kỳ giả định nào về việc lắp ghép có thể bị phá vỡ bởi một BLOB lớn hơn. Điều đó bao gồm những gì không phù hợp với trí nhớ. Tại một số điểm, việc xử lý luồng yêu cầu phát trực tiếp và lớp Buffer đang chọn 10K làm điểm bùng phát để từ bỏ và xử lý tệp bằng cách phát trực tuyến. –

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