Bagaimana saya bisa mengunduh file dari URL dan menyimpannya di Rails?

197

Saya memiliki URL ke gambar yang ingin saya simpan secara lokal, sehingga saya dapat menggunakan Paperclip untuk menghasilkan thumbnail untuk aplikasi saya. Apa cara terbaik untuk mengunduh dan menyimpan gambar? (Saya mencari penanganan file ruby ​​tetapi tidak menemukan apa pun.)

Alok Swain
sumber

Jawaban:

315

Coba ini:

require 'open-uri'
open('image.png', 'wb') do |file|
  file << open('http://example.com/image.png').read
end
Retribusi
sumber
1
Ini bekerja. Terima kasih. Saya mencoba ini pada gambar. Gambar tidak ditulis dengan benar ke file. Seolah sudah rusak atau apalah. Anda juga dapat membimbing saya untuk melakukan hal yang sama di aplikasi Rails. Bisakah saya menggunakan ini dalam aplikasi Rails?
Alok Swain
Ya, Anda dapat menggunakannya dalam aplikasi rel. File yang tidak ditulis dengan benar mungkin karena saya lupa membuka tujuan dalam mode binary. Saya akan mengeditnya sekarang.
Levi
78
Ini membaca seluruh file dalam memori. Cara terbaik adalahIO.copy_stream(open('http://example.com/image.png'), 'destination.png')
janko-m
3
rails 5, 2016, saya tidak perlu require 'open-uri', hanya menggunakan kode di bawahnya
Mirror318
1
jawaban ini tidak berhasil untuk saya. jawaban yang benar ada di sini: stackoverflow.com/a/29743394/1536309
Blair Anderson
147

Versi yang lebih pendek:

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

Untuk menjaga nama file yang sama:

IO.copy_stream(download, "~/#{download.base_uri.to_s.split('/')[-1]}")
Clemens Helm
sumber
2
Dan lebih efisien karena output tidak disimpan sebagai string di memori. +1
Itay Grudev
2
Meskipun sebenarnya bermanfaat jika kedua jawaban ditampilkan, sehingga orang-orang seperti saya dapat melihat keduanya, pikirkan perbedaannya dan kemudian pilih jawaban ini secara sadar untuk alasan yang tepat :)
Maxwell Evans
30

Jika Anda menggunakan PaperClip, pengunduhan dari URL sekarang ditangani secara otomatis.

Dengan asumsi Anda punya sesuatu seperti:

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

Pada model Anda, cukup tentukan gambar sebagai URL, sesuatu seperti ini (ditulis secara disengaja):

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

Anda mungkin ingin memasukkan metode ini ke dalam model Anda. Ini juga akan bekerja dengan baik pada sistem file sementara Heroku.

Penjepit kertas akan mengambilnya dari sana.

sumber: dokumentasi penjepit kertas

superluminary
sumber
4
Untuk pencari masa depan, Paperclip tidak lagi mengizinkan ini secara default: medium.com/in-the-weeds/…
Alex Dunae
14

Saya pikir ini adalah cara yang paling jelas:

require 'open-uri'

File.write 'image.png', open('http://example.com/image.png').read
Sage Ross
sumber
bijak saya baru ke rel, di mana saya dapat menambahkan kode ini dalam model atau controller atau dalam pandangan
adarsh
1
Tergantung, tetapi biasanya Anda akan melakukan hal seperti ini di dalam model atau metode pengontrol. Dalam konteks Rails, Anda mungkin lebih baik menggunakan alat kerangka kerja seperti ActiveStorage, daripada menulis langsung ke disk.
Sage Ross
10

Lihat Net :: HTTP di perpustakaan standar. Dokumentasi menyediakan beberapa contoh tentang cara mengunduh dokumen menggunakan HTTP.

Pär Wieslander
sumber
2
Jawaban ini membutuhkan lebih banyak visibilitas karena Kernel#openmemungkinkan tidak hanya akses file tetapi juga proses pemanggilan dengan awalan simbol pipa (misalnya, open("| ls")). Jadi, itu dapat menyebabkan risiko keamanan yang serius dengan menggunakan input variabel ke argumen Kernel#open.
ConorB