sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL Ukládání a vybírání souborů pomocí binárních dat Bytea s knihovnou C libpq

Toto je výsledek správného fungování kódu. Teď mám čas to zveřejnit pro případ, že by to někomu mohlo pomoci. Bylo pro mě trochu těžké pochopit, jak bytea funguje, ale nakonec je to vyřešeno. S pozdravem komunity.

#include <string>
#include <fstream>
#include <iostream>
#include <sstream>

#include "libpq/libpq-fs.h"
#include "libpq-fe.h"

#pragma comment(lib, "libpq.lib")   /*!< Only for windows compilation */

int main(int argc, char* argv[])
{
    ManageDB manager;       

    manager.conn = manager.ConnectDB();  // My manager, connects ok

    const char* fileName = {"test.png"};
    const char* fileNameOut = { "testOut.png" };

    FILE* file = fopen(fileName, "rb");
    if (file == NULL) cout << endl << "FILE WAS UNABLE TO BE READED" << endl;
    fseek(file, 0, SEEK_END);
    long int fileSize = ftell(file);

    rewind(file);

    unsigned char* buffRead = (unsigned char*)malloc(fileSize);
    size_t bytes_read = fread(buffRead, 1, fileSize, file);
    if (bytes_read != fileSize) cout << endl << "fread reading Error";
    fclose(file);
    
    size_t* sizeP = new size_t(fileSize);

    const char* paramValues[3];
    paramValues[0] = "1";
    paramValues[1] = fileName;
    paramValues[2] = reinterpret_cast<const char*>(buffRead);   // type cast required to PQexeParams

    const int paramFormats[3]{ 0,0,1 };   //0 = text, 1 = binary
    const int paramLenghts[3]{ strlen(paramValues[0]), strlen(paramValues[1]), fileSize};

    PGresult *res = PQexecParams(manager.conn, "INSERT INTO filebyte (id, filename, file) VALUES($1::text, $2::text, $3::bytea)",
        3,              /* params num */
        NULL,           /* let the backend deduce param type */
        paramValues,
        paramLenghts,
        paramFormats,
        1);

    if (res && PQresultStatus(res) == PGRES_COMMAND_OK) cout << endl << "Inserted data to filebyte OK";

    PQfreemem(res);

    //************************download from DB*************************
    
    const char* bytesFromDB = new const char[fileSize];
    int sizeR;
    // Table columns = id(text) | filename(text) | file(bytea)
    const char* sentenceEx = "SELECT file FROM filebyte WHERE id='1'";

    res = PQexec(manager.conn, sentenceEx);

    if (res && PQresultStatus(res) == PGRES_TUPLES_OK)
    {
        sizeR = PQgetlength(res, 0, 0);
        bytesFromDB = PQgetvalue(res, 0, 0);
    }
    else cout << endl << "Error at inserting file data in filebyte table";

    string hex(bytesFromDB, 2, sizeR-2);  //removing the first '\x' characters of the result.

    // vars for converting to real bytes process
    std::basic_string<uint8_t> bytes;
    bytes.clear();
    std::string nextbyte; 
    nextbyte.clear();
    uint16_t byte;

    // Iterate over every pair of hex values in the input string (e.g. "18", "0f", ...)
    for (size_t i = 0; i < hex.length(); i += 2)
    {
        // Get current pair and store in nextbyte
        nextbyte = hex.substr(i, 2);

        // Put the pair into an istringstream and stream it through std::hex for
        // conversion into an integer value.
        // This will calculate the byte value of your string-represented hex value.
        std::istringstream(nextbyte) >> std::hex >> byte;

        // As the stream above does not work with uint8 directly, we have to cast it now.
        // As every pair can have a maximum value of "ff",
        // which is "11111111" (8 bits), we will not lose any information during this cast.
        bytes.push_back(static_cast<uint8_t>(byte));
    }

    // string obj from bytes-"array"
    std::string result(begin(bytes), end(bytes));

    ofstream myFile(fileNameOut, ios::out | ios::ios_base::binary);
    
    if (myFile.is_open())
    {
        myFile << result;
        myFile.close();
    }
    else cout << endl << "Impossible to writte the file " << fileNameOut;
    
    manager.CloseConn(manager.conn);   //closes connection with database internally ok

    PQfreemem(res);
    free(buffRead);
    delete sizeP;
    free((char*)fileName[8]);
    free((char*)fileNameOut[11]);
    
    return true;
}



  1. Jak odstranit konkrétní znak z řetězce, pouze pokud je to první nebo poslední znak v řetězci.

  2. Pomozte mi pochopit rozdíl mezi CLOB a BLOB v Oracle

  3. Vytvořte novou tabulku sloučením dvou tabulek pomocí unie

  4. Oracle SQL:Použití funkce CHR() s || zřetězit