Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support raw binary output (and input) #506

Closed
nicklasaven opened this issue Feb 27, 2016 · 22 comments
Closed

Support raw binary output (and input) #506

nicklasaven opened this issue Feb 27, 2016 · 22 comments

Comments

@nicklasaven
Copy link

Would it be possible to find a good way to output raw binary data from PostgREST?

It would mean returning data like application/octet-stream
https://www.iana.org/assignments/media-types/application/octet-stream

The main problem is that it cannot be put in a json object which is text.

In PostgreSQL this type of data is stored as bytea.

@eric-brechemier
Copy link
Contributor

@nicklasaven What is your use case?

@nicklasaven
Copy link
Author

Hi, sorry for late reply

My use case might be rare, so maybe I should solve it in some other way.

But dealing with json is in many cases heavy and not the way to go.

I use PostGIS and are testing solutions with the new twkb export format.

That is a format that compresses the geoemtries by delta-encoding the coordinates and stores them as VarInts, the same way as protobuffer do.

So, what I want to do is getting thetwkb geometries out through the rest api.

But maybe with nginx in front I should get them directly from the db instead. But I like the level of security PostgREST adds by just accepting right formatted requests. It is an easy way to avoid any sql-injection problems.

@begriffs
Copy link
Member

begriffs commented Apr 3, 2016

Can you explain a little more? You're saying, for instance, that one of your tables has a column with big binary values, and you would like to return one of these values directly without it being embedded in JSON?

@geoervin
Copy link

geoervin commented Apr 4, 2016

My use case is pretty simple but I have not been to find a solution. I have a content type of application/pdf (blob) that I would like to write (post) to the database using the postgres bytea binary type. My attempts at using with text datatype with base64 encoding got me close but eventually became too complex to justify for my skill set.

@nicklasaven
Copy link
Author

My use case might be better to solve outside postgrest as discussed above, but it might be nice to ba able to do it inside postgrest too.

I saw in #257 that @begriffs suggests a one row return limitation. For my use case it would be better if the result was just concatenated. The format includes information about each parts length and have a defined ending for each geoemtry. So getting a long binary string scrubbed from the bytea meta-data would be the best.

Then the job is up to the client to rip it apart and render it on a map.

In my case the binary format also includes an ID so the geometry can be linked to attribute data client side.

But I am not sure this type of usage has a generic usage, so probably better to do in other ways.

An alternative could be a possibility to add a delimiter to the call, like the postgresql function string_agg(string, delimiter). In this case it should be an ascii sequence (or hex string or whatever) so there is no encoding problems when used as binary.

@diogob
Copy link
Contributor

diogob commented Apr 4, 2016

@nicklasaven would encoding the bytea field as base64 and keeping the json be a possible solution?
What is the size of such files in your case?

@geoervin
Copy link

geoervin commented Apr 4, 2016

When testing a write using Post the CSV format was easiest make work. I could not get an object to write with bytea, only text. My pdf blob's are only around 100k so even with encoding speed was not an issue. I just ran out of gas with encode/decode logic when retrieving from text due to my inexperience with front end (javascript).

@nicklasaven
Copy link
Author

@diogob Well, I guess base64 is a way to go. I tested and the encoding is very fast. That should work out of the box by just encoding in a view I guess. Only downside of course is the extra 33 % of size.

About sizes it can be anything. I mean the format really show off when used with large data sets, but then a rest-api isn't the way to go anyway.

@ghost
Copy link

ghost commented May 1, 2016

I'm looking for a similar feature. My use case is to receive binary image data directly via postgrest.
So i could use something like this

<img src="http://server:3000/image?id=eq.1&select=data">

@ruslantalpa
Copy link
Contributor

@JotPe just out of curiosity, what is the value of having image data in the database, why not files and keep url in the database?

@ghost
Copy link

ghost commented May 1, 2016

The pros and cons are discussed often. In my case, I want ACID binary data and a single point of storage.

@ruslantalpa
Copy link
Contributor

ruslantalpa commented May 1, 2016

what if you tried casting the data like
select=data:: bytea
The idea is if you can somehow in sql cast a (bynary) column to a string, you can get that with postgres.
But you can not use it directly as a url for your image, you have to decode it clientside (pass it through a js function)

@ghost
Copy link

ghost commented May 1, 2016

Yes, thanks.
But my intention was another use case for this feature request. Trying to avoid the use of a js function to convert the string representation of binary data to real binary data.

@ghost
Copy link

ghost commented May 29, 2016

Lack of knowledge, how could a prototype in Haskell look like?

@diogob
Copy link
Contributor

diogob commented May 29, 2016

@nicklasaven @JotPe you can use the PostgreSQL encode function. It's documented here. So any view exposed through PostgREST can take a bytea column and present it as base64. For small images this is very interesting since it lets you load then directly in the browser using image tags.

@ghost
Copy link

ghost commented May 29, 2016

Thanks. Of course I am using already img tags with an base64 data url, generated by the encode function in postgresql.
But I meant Haskell, how could a prototype looks like in the postgrest Haskell code to implement a raw binary output? Making this comment before possible?

@diogob
Copy link
Contributor

diogob commented May 29, 2016

@JotPe currently there would be a lot of hacking to support that example.
I believe the best way would be to create a new constructor for the type Action and an entirely different case in App.hs

@steve-chavez
Copy link
Member

@nicklasaven Would concatenating the binary rows with a '\n' be acceptable for your use case? I'm planning to implement this feature.

@nicklasaven
Copy link
Author

@steve-chavez interesting! Yes, I guess I can strip away the \n. Or could it be an option to just concatenating without any delimiter?

@begriffs
Copy link
Member

I merged @steve-chavez's pull request implementing this feature!

@W1M0R
Copy link

W1M0R commented Jun 26, 2020

@steve-chavez Does PostgREST support binary input? I'd like to post raw binary data (not base64) to /rpc/my_func, where my_func is a stored procedure that has one parameter of type bytea.

@steve-chavez
Copy link
Member

@W1M0R Not for now, but progress on binary input is being tracked at #922.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

8 participants