0

I am trying to connect my ios app (swift) to a postgres database through RestAPI (using npm and pg-promise)

Posting string and integer values worked like a charm, but I am having trouble posting images to the database

I am decoding the image into base64 string so I can send it to a POST request, and then posting the string into my table or decoding it to bytea before posting... both methods worked with some pictures and failed to work with other pictures giving me "not the correct format" error...

Here is my code

ios Swift

private static func request(todo: JSON -> ()) {

    let imageb = UIImageJPEGRepresentation(image, 0.7)
    let str64 = Helper.nsdataToStr64(imageb)

    Alamofire.request(.POST, 
                      "http://127.0.0.1:3000/api/photos", 
                      parameters: ["visit_id": 1, "photo" : str64])
        .responseJSON { (response) in
            switch response.result {
            case .Success:
                let results: JSON = JSON(data: response.data!)["data"]
                todo(results)
            case .Failure(let error):
                print("Failed: \(error)")
            }

    }
}

queries.js

function uploadPhoto(req, res, next) {
    req.body.visit_id = parseInt(req.body.visit_id);

    //db.one('insert into photos(visit_id, photo) values(${visit_id}, decode(${photo}, \'base64\')) returning _id',
    //  req.body)
    db.one('insert into photos(visit_id, base64) values(${visit_id}, ${photo}) returning _id',
      req.body)
    .then(function (data) {
      res.status(200)
      .json({ 
        status: 'success',
        data: data,
        message: 'Inserted one photo' 
      });
    }) 
    .catch(function (err) {
      return next(err);
      //console.log("ERROR:", err.message || err);
    });
}

now, this method works flawlessly with this picture and many more but fails with this picture and many more.. Any idea why? I noticed that if the picture is more than a few hundred kilobytes, the post method fails... Is this possible? and why? is there a way to solve this problem?

Note: all the pictures are of jpg format, so the format is not the problem

Anya Alstreim
  • 133
  • 12
  • If you pass the image into `pg-promise` directly, as a `Buffer` object, it gets automatically encoded by the library into proper base64 presentation for PostgreSQL. See [example](https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#insert-binary). – vitaly-t Aug 20 '16 at 14:08
  • How do you pass the image into pg-promise from a request? the parameters for a request accepts only string values @vitaly-t – Anya Alstreim Aug 20 '16 at 17:42
  • in a standard way, post it as form-attached data. Or you can stream it in. – vitaly-t Aug 20 '16 at 17:48

1 Answers1

0

Something has got to be wrong in the way you that you encode and/or pass in the data into the service.


I took your problematic picture, which is a beautiful one btw, saved it locally and then inserted it into the database using the direct approach as explained here.

The picture inserted without any problems.

Here's complete application:

var fs = require('fs');

let pgp = require('pg-promise')();

let db = pgp("postgres://postgres@localhost:5433/newone");

fs.readFile('c:/temp/Bella.jpg', function (err, imgData) {
    db.one('insert into images(img) values($1) returning id', imgData, i=>i.id)
        .then(id=> {
            console.info(id);
        })
        .catch(err=> {
            console.error(err);
        });
});

Outputs new record Id: 1

Table I used:

create table images (
    id serial primary key,
    img bytea not null
);

Reading the data back and saving it resulted in the same valid picture.


You need to investigate where the image data gets corrupted while on the way to the service ;) It seems likely that some of your image serialization breaks the data.

And since the problem manifests itself for a large image, I would suggest attaching a checksum to the image data, so it is easier to find out on which step the data becomes corrupted ;)

vitaly-t
  • 24,279
  • 15
  • 116
  • 138