Làm cách nào tôi có thể tải xuống một tệp từ một URL và lưu nó trong Rails?


197

Tôi có một URL tới một hình ảnh mà tôi muốn lưu cục bộ, để tôi có thể sử dụng Paperclip để tạo hình thu nhỏ cho ứng dụng của mình. Cách tốt nhất để tải xuống và lưu hình ảnh là gì? (Tôi đã xem xét xử lý tập tin ruby ​​nhưng không bắt gặp bất cứ điều gì.)

Câu trả lời:


315

Thử cái này:

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end

1
Những công việc này. Cảm ơn. Tôi đã thử điều này trên một hình ảnh. Hình ảnh không được ghi đúng vào tập tin. Như thể nó đã bị hỏng hoặc một cái gì đó. Bạn cũng có thể hướng dẫn tôi làm điều này trong ứng dụng Rails. Tôi có thể sử dụng điều này trong một ứng dụng Rails không?
Alok Swain

Có, bạn có thể sử dụng nó trong một ứng dụng đường ray. Các tập tin không được viết đúng có lẽ là do tôi quên mở đích ở chế độ ghi nhị phân. Tôi sẽ chỉnh sửa nó ngay bây giờ.
Levi

78
Điều này đọc toàn bộ tập tin trong bộ nhớ. Cách tốt nhất làIO.copy_stream(open('http://example.com/image.png'), 'destination.png')
janko-m

3
rails 5, 2016, tôi không cần require 'open-uri', chỉ sử dụng mã bên dưới nó
Mirror318

1
Câu trả lời này không làm việc cho tôi. câu trả lời đúng là ở đây: stackoverflow.com/a/29743394/1536309
Blair Anderson

147

Một phiên bản thậm chí ngắn hơn:

require 'open-uri'
download = open('http://example.com/image.png')
IO.copy_stream(download, '~/image.png')

Để giữ cùng tên tệp:

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")

2
Và hiệu quả hơn vì đầu ra không được lưu dưới dạng một chuỗi trong bộ nhớ. +1
Itay Grudev

2
Mặc dù thực sự hữu ích khi có cả hai câu trả lời được hiển thị, vì vậy những người như tôi có thể thấy cả hai, suy nghĩ về sự khác biệt và sau đó chọn câu trả lời này một cách có ý thức vì những lý do chính đáng :)
Maxwell Evans

30

Nếu bạn đang sử dụng PaperClip, việc tải xuống từ một URL sẽ được xử lý tự động.

Giả sử bạn đã có một cái gì đó như:

class MyModel < ActiveRecord::Base
  has_attached_file :image, ...
end

Trên mô hình của bạn, chỉ cần chỉ định hình ảnh dưới dạng URL, đại loại như thế này (được viết bằng tay có chủ ý):

@my_model = MyModel.new
image_url = params[:image_url]
@my_model.image = URI.parse(image_url)

Bạn có thể muốn đưa điều này vào một phương thức trong mô hình của bạn. Điều này cũng sẽ hoạt động tốt trên hệ thống tập tin tạm thời của Heroku.

Paperclip sẽ lấy nó từ đó.

nguồn: tài liệu kẹp giấy


4
Đối với những người tìm kiếm trong tương lai, Paperclip không còn cho phép điều này theo mặc định: Medium.com/in-the-weed/iêu
Alex Dunae

14

Tôi nghĩ rằng đây là cách rõ ràng nhất:

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read

hiền tôi mới làm quen với đường ray, nơi tôi có thể thêm mã này vào mô hình hoặc bộ điều khiển hoặc trong chế độ xem
adarsh

1
Nó phụ thuộc, nhưng thông thường bạn sẽ làm một cái gì đó như thế này trong một mô hình hoặc phương thức điều khiển. Trong ngữ cảnh Rails, có khả năng bạn nên sử dụng các công cụ của khung như ActiveStorage, thay vì ghi trực tiếp vào đĩa.
Sage Ross

10

Kiểm tra Net :: HTTP trong thư viện chuẩn. Tài liệu này cung cấp một số ví dụ về cách tải xuống tài liệu bằng HTTP.


2
Câu trả lời này cần nhiều khả năng hiển thị hơn vì Kernel#openkhông chỉ cho phép truy cập tệp mà còn xử lý việc gọi bằng cách thêm tiền tố vào biểu tượng ống (ví dụ open("| ls"):). Vì vậy, nó có thể dẫn đến rủi ro bảo mật nghiêm trọng bằng cách sử dụng đầu vào biến đổi cho đối số Kernel#open.
ConorB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.