2013-04-14 10 views
8

Od kilku stanowisk widziałem, próbuję tootwierać i zapisywać dane zakodowane base64 obrazu URI w Ruby

x = Base64.decode64("data:image/png;base64,iVBOR....") 
File.open('test.png','wb') {|file| file.write x} 

Ale wtedy nie można otworzyć obrazu z widzem, muszę zrobić coś więcej?

+0

Pardon mój włamań: na wszelki wypadek przyjechałeś tutaj (tak jak ja) szukając base64 PNG * kodować * oneliner w ruby: '" dane: image/png; base64, "+ Base64.strict_encode64 (File.read (" test.png "))' - carry na. :) –

Odpowiedz

23

Twój problem polega na tym, że próbujesz zdekodować prefiks 'data:image/png;base64,' jako dane Base64; ten prefiks jest całkowicie poprawny dla danych Base64, ale nie jest reprezentacją pliku PNG w Base64. W rezultacie plik test.png zawiera kilka bzdur, a następnie kilka bitów, które w rzeczywistości są plikiem PNG. Odpędzenia prefiks URL dane przed dekodowania PNG:

data_url = "data:image/png;base64,iVBOR...." 
png  = Base64.decode64(data_url['data:image/png;base64,'.length .. -1]) 
File.open('test.png', 'wb') { |f| f.write(png) } 
+3

Jak wykryłbyś kilka formatów? Zrobiłem 'data_url.match (/ data: (. *); Base64, (. *) /)', Aby uzyskać typ kodowania, format pliku i dane obrazu, ale ja nie jestem pewien, czy może to spowodować problem z wydajnością, gdy łańcuch jest duży. – juanpastas

+0

@juanpastas: Zakotwicz regex na początku i użyj prostych operacji na łańcuchach, aby usunąć prefiks. A może chcesz być nieco bardziej konkretny, jak wygląda typ MIME. –

+0

Obsługiwane typy MIME to: image/png, image/jpg – juanpastas

5

mu_is_too_short odpowiedź jest dość blisko, ale zakłada, że ​​strumień base64 będzie zawierać dane PNG. To nie zawsze tak jest, więc proponuję używać typów MIME biblioteki w celu ustalenia prawidłowej Rozszerzenie pliku:

REGEXP = /\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m 

data_uri_parts = data_url.match(REGEXP) || [] 
extension = MIME::Types[data_uri_parts[1]].first.preferred_extension 
file_name = "myfilename.#{extension}" 

File.open(file_name, 'wb') do |file| 
    file.write(Base64.decode64(data_uri_parts[2])) 
end 
0

to trochę skrypt o tym, jak otworzyć obraz base64, vacio.txt jest plik kiedy mam tekst base64 .

require 'base64' 
entry="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQE....." 
File.open("vacio.txt","r") do |fichero| 
while linea=fichero.gets 
    regex=/(data:image\/\D*\d*,)/ 
    m=regex.match(linea) 
    png=Base64.decode64(linea[m.to_s.length .. -1]) 
    File.open('test.jpeg','wb'){|f|f.write(png)} 
end 
end 
1

Zamiast korzystać z Regexp, można również skorzystać z prostego String#index metody.

Zwraca indeks pierwszego występowania danego fragmentu lub typu (regexp) na str. Zwraca zero, jeśli nie znaleziono.

Jeśli masz dość rozsądny źródło danych (np JavaScript na .toDataURL() na canvas), można powołać się na fakt, że wspólne MIMETYPES nie może zawierać przecinków.

dataURL = "data:image/png;base64,iVBOR...." 
start = dataURL.index(',') + 1     # .index used here 
x = Base64.decode64 dataURL[start..-1] 
File.open('test.png','wb') {|file| file.write x} 

Jeśli pracujesz z free-form przesyłania plików użytkownika, pamiętaj, że kilka rzadkie typy MIME nie zawierają przecinki (np .: text/x-java-source,java). Można użyć bardziej konserwatywny:

start = dataURL.index(';base64,') + 8 

Jeśli nie wiem, czy masz prefiksu base64 lub URL base64 danych, można użyć #index jako test:

start = dataURL.index ';base64,' 
dataURL = dataURL[(start+8)..-1] if start 
x = Base64.decode64 dataURL 
Powiązane problemy