phpsqljsonpython-2.7advantage-database-server

How to insert file upload content to database by sending base64 encoded file content via json?


From my php page I send file upload content as

$imgData = addslashes(file_get_contents($_FILES['userImage']['tmp_name']));
$imgData= base64_encode($imgData);

then send this to payload - REST API in python

$call->send('{"payload" : { "dbstr" :"' . DEF_DB . '", "tblCode" : "' . USE_INF . '", "use_cod": "'.$use_cod.'", "use_pas": "'.$use_pas.'","use_nam": "'.$use_nam.'","use_dob": "'.$use_dob.'","use_ema": "'.$use_ema.'","use_des": "'.$use_des.'","use_pfe": "'.$imgData.'"}');

then in my python code I write like this

use_pfe = item_dict['payload']['use_pfe']
imgdata1 = use_pfe.encode("utf-8")
imgdata2 = base64.b64decode(imgdata1)

Now I try inserting this to my database using sql where the image column is binary(blob) type

cursUserAU.execute("insert into " + tblCode + " (use_cod, use_pass, use_nam, use_dob, use_email, use_desig, use_profile) values ('" + use_cod +"' , '"+ use_pas +"', '"+ use_nam +"', '"+ use_dob +"', '"+ use_ema +"', '"+ use_des +"', "+ imgdata2 +")")

but this end in error... Am I doing in right way ? or there any part missing ? I dont want to save this file in any directory I just want to save this directly in db. Please help me with suggestion or any resources. Thanks in advance.

More detials is as follows

I am using adsdb python driver to connect advantage database server database.

in python

connUserAU = adsdb.connect(DataSource=datasource, ServerType='3', UserID='adssys', Password='')
cursUserAU = connUserAU.cursor()
sql = "insert into " + tblCode + " (use_cod, use_pass, use_nam, use_dob, use_email, use_desig, use_profile) values (?, ?, ?, ?, ?, ?, ?)"
cursUserAU.execute(sql, (use_cod, use_pas, use_nam, use_dob, use_ema, use_des, imgdata))
connUserAU.commit()
cursUserAU.close()

above use_profile is blob column type

here are the database column types

use_cod Char( 10 ),
use_pass Char( 10 ),
use_nam Char( 30 ),
use_dob Date,
use_email Char( 50 ),
use_desig Char( 30 ),
use_profile Blob,
user_gender Char( 1 ),
use_profile2 CIChar( 50 )

Solution

  • In your PHP code, after you make the call file_get_contents($_FILES['userImage']['tmp_name']), the return value is a string containing the contents of your image, which is binary data. You should not be escaping this content as if these were actual characters. So this line should just be:

    $imgData = file_get_contents($_FILES['userImage']['tmp_name']);
    

    Therefore, in your Python code, use_pfe will be the base64-encoded image. This will be a string of ASCII characters. The line ...

    imgdata1 = use_pfe.encode("utf-8")
    

    ... converts use_pfe into a byte string encoded using utf-8 encoding. But, because this is Python 2 where a byte string is the same thing as a simple character string (that is, type str as opposed to a unicode string, that is, type unicode) and the characters being encoded are from the ASCII character set, which can be encoded in a single byte, you end up with imgdata1 being identical to use_pfe. In effect, this statement does nothing. However, if this were Python 3, where byte strings, type bytes, are different from character strings, which are unicode strings, type str, this line would be incorrect: You need to leave the input as type str for input to the next line, which is converting the base64 string back to a byte string.

    Putting this together:

    PHP:

    $imgData = file_get_contents($_FILES['userImage']['tmp_name']);
    $imgData = base64_encode($imgData);
    

    Python:

    use_pfe = item_dict['payload']['use_pfe']
    imgdata2 = base64.b64decode(use_pfe)
    

    You should be doing your table insert as follows with a Prepared Statement, which not only simplifies passing the values but also avoids the possibility of SQL Injection attacks when the values are user-supplied. The place-holders for the arguments below are ?, which I believe is correct for your database (for MySql and PostgreSQL and most other relational databases, use %s).

    # make it more readable:
    sql = "insert into " + tblCode + " (use_cod, use_pass, use_nam, use_dob, use_email, use_desig, use_profile) values (?, ?, ?, ?, ?, ?, ?)"
    cursUserAU.execute(sql, (use_cod, use_pas, use_nam, use_dob, use_ema, use_des, imgdata2))
    

    But the above is causing:

    UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)`

    Now you must provide a complete description of every column in your table tblCode including the character set being used. Also, print out for each argument being passed, type(argument) For example:

    print type(use_cod), type(use_pas), type(use_nam), ... type(imgdata2)
    

    But to save time, let me ask the most likely cause of the problem: Are you using a BLOB type for column use_profile?