2011-07-18 13 views
18

Obecnie mam wiele plików przechowywanych w postgresie 8.4 jako bajt. Typy plików to .doc, .odt, .pdf, .txt i itp.Jak pobrać kolumnę Postgres bytea jako plik

Czy mogę wiedzieć, jak pobrać cały plik przechowywany w PostgreSQL, ponieważ muszę wykonać kopię zapasową. Potrzebuję ich w oryginalnym pliku, zamiast w formacie Beta.

Dzięki!

+3

Jest to rodzaj niepowiązane, ale należy pamiętać, że w Postres 9.0 domyślnych 'bytea_output' zmian od' encode' na 'hex'. Zobacz [uwagi do wydania] (http://www.postgresql.org/docs/9.2/static/release-9-0.html) –

Odpowiedz

0

Najlepiej sobie zdawać sprawę, że pliki do pobrania muszą zostać wykonane na poziomie aplikacji.

(9,1 może zmienić to z contrib plików danych owijarki. Jest też funkcja lo_export, ale to nie ma zastosowania tutaj.)

+0

Witam, czy możesz podać przykładowy kod do pobrania bytea do pliku w aplikacji poziom. Dzięki! –

+0

Błąd ... Powinieneś mieć ten kod, aby wyświetlić pliki. Po prostu zapisz strumień. –

28

Prostym rozwiązaniem jest użycie komendy COPY z encode do formatu hex, a następnie zastosować xxd Polecenie powłoki (z przełącznikiem -p ciągłym przełącznikiem hexdump). Na przykład załóżmy, że mam jpg obraz w kolumnie bytea w próbkach tabeli:

\copy (SELECT encode(file, 'hex') FROM samples LIMIT 1) TO 
    '/home/grzegorz/Desktop/image.hex' 

$ xxd -p -r image.hex > image.jpg 

Jak sprawdziłem to działa w praktyce.

+1

Czy można w tym celu polegać na xxd? Czy nie ma rozwiązania opartego wyłącznie na postgresql, aby uzyskać kopię? – Marcel

+0

@Marcel Możesz użyć 'while read -N2 code; do printf "\ x kod $"; zrobione image.jpg' zamiast xxd. To nie jest czysty postgresql, ale do tego potrzebujesz tylko bash. Mówią, że xxd jest częścią pakietu vim. – user3132194

0

Jeśli masz dużo danych do pobrania, możesz najpierw pobrać wiersze, a następnie powtórzyć każdy z zapisanych pól bytea do pliku.

$resource = pg_connect('host=localhost port=5432 dbname=website user=super password=************'); 

// grab all the user IDs 
$userResponse = pg_query('select distinct(r.id) from resource r 
         join connection c on r.id = c.resource_id_from 
         join resource rfile on c.resource_id_to = rfile.id and   rfile.resource_type_id = 10 
         join file f on rfile.id = f.resource_id 
         join file_type ft on f.file_type_id = ft.id 
         where r.resource_type_id = 38'); 

// need to work through one by one to handle data 
while($user = pg_fetch_array($userResponse)){ 
    $user_id = $user['id']; 
    $query = 'select r.id, f.data, rfile.resource_type_id, ft.extension from resource r 
         join connection c on r.id = c.resource_id_from 
         join resource rfile on c.resource_id_to = rfile.id and rfile.resource_type_id = 10 
         join file f on rfile.id = f.resource_id 
         join file_type ft on f.file_type_id = ft.id 
         where r.resource_type_id = 38 and r.id = ' . $user_id; 

    $fileResponse = pg_query($query); 
    $fileData = pg_fetch_array($fileResponse); 
    $data = pg_unescape_bytea($fileData['data']); 
    $extension = $fileData['extension']; 
    $fileId = $fileData['id']; 
    $filename = $fileId . '.' . $extension; 
    $fileHandle = fopen($filename, 'w'); 
    fwrite($fileHandle, $data); 
    fclose($fileHandle); 
} 
1

Spróbuj tego:

COPY (SELECT yourbyteacolumn FROM yourtable WHERE <add your clauses here> ...) TO 'youroutputfile' (FORMAT binary) 
+1

To działa; ale wyjście wymaga dodatkowego przetwarzania. Zobacz [Format binarny] (https://www.postgresql.org/docs/9.6/static/sql-copy.html#AEN77714) – Sjon

+0

Należy uciąć binarne nagłówki i stopki. Zgadzam się, odpowiedź nie jest kompletna. –