Хранение и извлечение zip-файлов в SQLite дает Не удалось декодировать в UTF-8

У меня есть следующая таблица в SQLite 3, и я планирую использовать ее для хранения различных файлов: txt, pdf, изображений и zip-файлов.

CREATE TABLE zip (filename TEXT PRIMARYKEY NOT NULL, zipfile BLOB NOT NULL);

Для хранения и извлечения я экспериментирую со следующим кодом Python

#!env/bin/python


import sqlite3 as lite
import os
import sys

def insertfile(_filename):
    try:
        con = lite.connect('histogram.db', detect_types=lite.PARSE_DECLTYPES)
        con.row_factory = lite.Row
        cur = con.cursor()
        cur.execute('PRAGMA foreign_keys=ON;')
        _f = open(_filename,'rb')
        _split = os.path.split(_filename)
        _file = _split[1]
        _blob = _f.read()
        cur.execute('INSERT INTO zip (filename,zipfile) VALUES (?,?)', (_file,lite.Binary(_blob)))
        _f.close()
        con.commit()
        cur.close()
        con.close()
    except Exception as ex:
        print ex

def getfile(_filename):
    try:
        con = lite.connect('histogram.db', detect_types=lite.PARSE_DECLTYPES)
        con.row_factory = lite.Row
        cur = con.cursor()
        cur.execute('PRAGMA foreign_keys=ON;')
        cur.execute('SELECT zipfile from zip where filename = ?', (_filename,))
        _files = cur.fetchall()
        if len(_files) > 0:
            _file  = open('Test/'+ _filename,'wb')
            _file.write(_files[0]['zipfile'])
            _file.close()
        cur.close()
        con.close()
    except Exception as ex:
        print ex

if __name__ == '__main__':
    print 'works'
    insertfile(sys.argv[1])
    getfile(os.path.split(sys.argv[1])[1])

Когда я проверяю это на таких файлах, как .txt, .py, .pdf и т. д., все работает нормально.

С Zip-файлами при сохранении в таблицу нет ошибки, но возникает ошибка при извлечении файла:

Не удалось декодировать столбец UTF-8 "zipfile" с текстом "PK"

Кажется, есть какая-то проблема с кодировкой или декодированием.


person v_radhakrishnan    schedule 12.12.2017    source источник
comment
Эти типы файлов изначально не поддерживаются на python. Если вы попытаетесь открыть эти типы файлов в блокноте, вы увидите, что это случайные аннотации.   -  person Usernamenotfound    schedule 12.12.2017
comment
Спасибо, но я просто пытаюсь сохранить байты файла — откройте с параметрами «rb» и «wb», чтобы сохранить файлы в виде двоичных данных. Мне удалось решить проблему для pdf, png и т. д., сохранив файл с помощью lite.Binary(_blob). Zip-файлы все еще вызывают у меня проблемы при поиске   -  person v_radhakrishnan    schedule 12.12.2017
comment
Не могли бы вы вставить полную трассировку?   -  person Daniel    schedule 12.12.2017
comment
@Daniel Код теперь работает. Не уверен, как проблема с zip-файлом была исправлена. Просто чтобы попробовать, я закомментировал вставку и просто запустил поиск, и это сработало. Теперь, когда я раскомментировал вставку, программа работает нормально. Не знаю, почему zip-файлы раньше выдавали ошибку.   -  person v_radhakrishnan    schedule 12.12.2017
comment
Может ли быть так, что detect_types=lite.PARSE_DECLTYPES пытается преобразовать ваш байт-блоб в строку UTF-8, но терпит неудачу, потому что это недопустимая строка UTF-8? Я бы удалил это и попробовал еще раз.   -  person Daniel    schedule 12.12.2017
comment
Рад слышать. Пожалуйста, запишите это как ответ и примите его.   -  person Daniel    schedule 12.12.2017


Ответы (1)


Я в основном пытался использовать код из одного из вопросов

Вставьте двоичный файл в базу данных SQLite с помощью Python.

Первоначально он работал для файлов pdf, png, jpg. Но я все еще получал ошибку для файлов Zip. Когда я закомментировал вставку и просто запустил код поиска, он сработал. Теперь приведенный ниже код работает.

def insertfile(_filename):
    try:
        con = lite.connect('histogram.db', detect_types=lite.PARSE_DECLTYPES)
        con.row_factory = lite.Row
        cur = con.cursor()
        cur.execute('PRAGMA foreign_keys=ON;')
        _f = open(_filename,'rb')
        _split = os.path.split(_filename)
        _file = _split[1]
        _blob = _f.read()
        cur.execute('INSERT INTO zip (filename,zipfile) VALUES (?,?)', (_file,lite.Binary(_blob)))
        _f.close()
        con.commit()
        cur.close()
        con.close()
    except Exception as ex:
        print ex

def getfile(_filename):
    try:
        con = lite.connect('histogram.db', detect_types=lite.PARSE_DECLTYPES)
        con.row_factory = lite.Row
        cur = con.cursor()
        cur.execute('PRAGMA foreign_keys=ON;')
        cur.execute('SELECT zipfile from zip where filename = ?', (_filename,))
        _files = cur.fetchall()
        if len(_files) > 0:
            _file  = open('Downloads/'+ _filename,'wb')
            _file.write(_files[0]['zipfile'])
            _file.close()
        cur.close()
        con.close()
    except Exception as ex:
        print ex

if __name__ == '__main__':
    print 'works'
    insertfile(sys.argv[1])
    getfile(os.path.split(sys.argv[1])[1])
person v_radhakrishnan    schedule 12.12.2017