Swift 5 - How to convert LONGBLOB/Buffer into Data - javascript

I am currently working on a project for school.
I have written an API using Express connected to a mysql database. And now I am writing the iOS app.
My problem is that I need to save profile pictures. So I saved the png data of the picture into a **LONGBLOB** into db and I want to recreate the image into a **UIImage**.
To do that I am trying to convert the buffer into ```Data```
So, the API is returning a buffer created that way:
let buffer = Buffer.from(ppData.data, 'binary').toString('base64');
And on the iOS side I tried:
guard let data = dict["data"] as? Data else {return nil}
Where dict["data"] is the buffer returned by the API.
But it always enter into the "else" part.
What am i doing wrong
Edit:
As what it was said in comments, I decoded the Base64 encoded string. Now the data are decoded but creating a UIImage from it, fails, without any details. What I tried is:
let image = UIImage(from: base64DecodedData)
For example:
guard let strData = dict["data"] as? String else {
return nil
}
guard let data = Data(base64Encoded: strData, options: .ignoreUnknownCharacters) else {
return nil
}
guard let picture = UIImage(data: data) else {
return nil
}
Thanks.

The mistake was not in the swift code part but in my API and database structure. After reading some MySQL and Node.js documentaion, I switched from LONGBLOB (which is totally oversized) to MEDIUMTEXT.
Also, in the API I was trying to create a buffer from binary data but not from a base64 string encoded data, so I removed this line:
let buffer = Buffer.from(ppData.data, 'binary').toString('base64');

Related

Trying to parse JSON

I'm a complete beginner at node.js and trying to figure out how to send the contents of a JSON-object using REST. My code only results in an error saying "SyntaxError: Unexpected token  in JSON at position 0". I have used an online validator to see that the JSON is corrent. What is the issue?
// GET courses
const fs = require('fs');
app.get('/api/courses', function(req, res) {
var rawdata = fs.readFileSync('miun-db.json');
var data = JSON.parse(rawdata);
res.send(data.courses);
});
The data inside of your file is not formatted properly. Verify that miun-db.json is properly formatted before attempting to parse.
The issue is that your file is not properly formatted, check this out Working with JSON.
Also you can just import the JSON file and use it without fs.
import miunDb from './miun-db.json';
app.get('/api/courses', function(req, res) {
res.send(miunDb.courses);
});
According to the fs.readFileSync docs you can pass options to the function.
fs.readFileSync(path[, options])
If the encoding option is specified then this function returns a string. Otherwise it returns a buffer.
Since you don't pass any options you get a buffer and not the string content of the file.
Either you pass encoding to the function, e.g.
var rawdata = fs.readFileSync('miun-db.json', {encoding:'utf8'});
var data = JSON.parse(rawdata);
or you convert the buffer to string. E.g.
var rawdata = fs.readFileSync('miun-db.json');
var data = JSON.parse(rawdata.toString('utf8'));
Edit:
Your error message says you have an invalid character which is non printable. Seems like your file starts with a BOM (zero width no-break space (ZWNBSP)).
What happens if you try to remove it?
function stripBOM(content) {
content = content.toString()
// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
// because the buffer-to-string conversion in `fs.readFileSync()`
// translates it to FEFF, the UTF-16 BOM.
if (content.charCodeAt(0) === 0xFEFF) {
content = content.slice(1)
}
return content
}
// [...]
var rawdata = fs.readFileSync('miun-db.json', {encoding:'utf8'});
var data = JSON.parse(stripBOM(rawdata));
// [...]
Credit goes to this gist.

Javascript ArrayBuffer equivalent in Swift or iOS

I want to know what is the Javascript ArrayBuffer equivalent in Swift or ios.
Basically I have a Swift struct that I want to store as a blob (data stored based on memory layout) and pass this blob to Javascript ArrayBuffer where I can , based on defined set layout extract data from ArrayBuffer
I havent yet managed to save the struct from Swift as a binary/memory blob. Struggling to understand the memory layout configuration. I thought it would be similar to structs in C but they are not.
Any help or pointers would be appreciated. Thanks.
I'm not an expert in Javascript, so I may be talking nonsense.
It seems like you can achieve what you want if your struct S implements the Codable protocol. Then you can transform it to a Data blob using an encoder, like this:
let encoder = JSONEncoder()
do {
let data = try encoder.encode(s)
// do what you want with the blob
} catch {
// handle error
}
And back to S, like this:
let decoder = JSONDecoder()
do {
let s = try decoder.decode(S.self, from: data)
} catch {
// handle error
}
If S is Codable, [S] (an Array<S>) will also be Codable.
You can probably pass the data to your scriptas a String, then you'll have to transform your data do string with JSONSerialization

Convert TCP Data in with pipe to JSON

Sorry if the issue is not particularly clear (I am still a novice). I have a simple setup to get data from a mock feed and then convert the data to JSON. I can retrieve the data and display it but converting it to JSON has proved a bit tricky.
var completeData = '';
let client = net.createConnection({ port: 8282 }, () => {
client.write('Test Worked!\r\n');
});
client.on('data', (data) => {
// change buffer to string
let readData = data.toString();
// Merge response data as one string
completeData += readData += '\n';
// End client after server's final response
client.end();
});
This is the sample output for one packet below (Pipe delimited with some data escaped):
|2054|create|event|1497359166352|ee4d2439-e1c5-4cb7-98ad-9879b2fd84c2|Football|Sky Bet League Two|\|Accrington\| vs \|Cambridge\||1497359216693|0|1|
I would like the pipes to represent keys/values in an object. The issue is that some of the values are escaped (e.g '\|' ). That kind of makes using the split function in Javascript difficult.
My question is there a way to get pipe delimited data from TCP packets and then convert them to a JSON object?
Any help will be highly appreciated. Thank you.
const { StringDecoder } = require("string_decoder");
let header = "";
const decoder = new StringDecoder("utf8");
let str = decoder.write(chunk); // chunk is your data stream
header += str;
header.replace(/s/, "");
var obj = JSON.parse(header);
console.log(obj);
While receiving data through tcp ip net npm package, we face trouble in parsing the continous stream of data. string_decoder is a npm package which can parse it into a json readable format. Also since the packets being received has a variable length so one can basically put a check on header.length to fetch only a complete set of object.

Extracting gzip data in Javascript with Pako - encoding issues

I am trying to run what I expect is a very common use case:
I need to download a gzip file (of complex JSON datasets) from Amazon S3, and decompress(gunzip) it in Javascript. I have everything working correctly except the final 'inflate' step.
I am using Amazon Gateway, and have confirmed that the Gateway is properly transferring the compressed file (used Curl and 7-zip to verify the resulting data is coming out of the API). Unfortunately, when I try to inflate the data in Javascript with Pako, I am getting errors.
Here is my code (note: response.data is the binary data transferred from AWS):
apigClient.dataGet(params, {}, {})
.then( (response) => {
console.log(response); //shows response including header and data
const result = pako.inflate(new Uint8Array(response.data), { to: 'string' });
// ERROR HERE: 'buffer error'
}).catch ( (itemGetError) => {
console.log(itemGetError);
});
Also tried a version to do it splitting the binary data input into an array by adding the following before the inflate:
const charData = response.data.split('').map(function(x){return x.charCodeAt(0); });
const binData = new Uint8Array(charData);
const result = pako.inflate(binData, { to: 'string' });
//ERROR: incorrect header check
I suspect I have some sort of issue with the encoding of the data and I am not getting it into the proper format for Uint8Array to be meaningful.
Can anyone point me in the right direction to get this working?
For clarity:
As the code above is listed, I get a buffer error. If I drop the Uint8Array, and just try to process 'result.data' I get the error: 'incorrect header check', which is what makes me suspect that it is the encoding/format of my data which is the issue.
The original file was compressed in Java using GZIPOutputStream with
UTF-8 and then stored as a static file (i.e. randomname.gz).
The file is transferred through the AWS Gateway as binary, so it is
exactly the same coming out as the original file, so 'curl --output
filename.gz {URLtoS3Gateway}' === downloaded file from S3.
I had the same basic issue when I used the gateway to encode the binary data as 'base64', but did not try a whole lot around that effort, as it seems easier to work with the "real" binary data than to add the base64 encode/decode in the middle. If that is a needed step, I can add it back in.
I have also tried some of the example processing found halfway through this issue: https://github.com/nodeca/pako/issues/15, but that didn't help (I might be misunderstanding the binary format v. array v base64).
I was able to figure out my own problem. It was related to the format of the data being read in by Javascript (either Javascript itself or the Angular HttpClient implementation). I was reading in a "binary" format, but it was not the same as that recognized/used by pako. When I read the data in as base64, and then converted to binary with 'atob', I was able to get it working. Here is what I actually have implemented (starting at fetching from the S3 file storage).
1) Build AWS API Gateway that will read a previously stored *.gz file from S3.
Create a standard "get" API request to S3 that supports binary.
(http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-configure-with-console.html)
Make sure the Gateway will recognize the input type by setting 'Binary types' (application/gzip worked for me, but others like application/binary-octet and image/png should work for other types of files besides *.gz). NOTE: that setting is under the main API selections list on the left of the API config screen.
Set the 'Content Handling' to "Convert to text(if needed)" by selecting the API Method/{GET} -> Integration Request Box and updating the 'Content Handling' item. (NOTE: the example in the link above recommends "passthrough". DON'T use that as it will pass the unreadable binary format.) This is the step that actually converts from binary to base64.
At this point you should be able to download a base64 verion of your binary file via the URL (test in browser or with Curl).
2) I then had the API Gateway generate the SDK and used the respective apiGClient.{get} call.
3) Within the call, translate the base64->binary->Uint8 and then decompress/inflate it. My code for that:
apigClient.myDataGet(params, {}, {})
.then( (response) => {
// HttpClient result is in response.data
// convert the incoming base64 -> binary
const strData = atob(response.data);
// split it into an array rather than a "string"
const charData = strData.split('').map(function(x){return x.charCodeAt(0); });
// convert to binary
const binData = new Uint8Array(charData);
// inflate
const result = pako.inflate(binData, { to: 'string' });
console.log(result);
}).catch ( (itemGetError) => {
console.log(itemGetError);
});
}

How to post and get data uri image from web api?

I am trying to post data uri image from javascript to backend asp.net webapi. However, it gives me input is not a valid Base-64 string error. Now, I understand that it may be due to "data:image/png;base64," part that the data uri contain.
Now, even if I remove this part from the data uri and send only the rest of the string to server, how do I store the Base-64 string on the server?
Moreover, how to retrieve this data as image from webapi?
NOTE: Image would be less than 200kB size and hence is to be stored as varbinary(Max) in sql server.
The thing is you should convert your image to byte[] and store it in your server as varbinary
byte []arr = new byte[image1.ContentLength];
image1.InputStream.Read(arr, 0, image1.ContentLength);
While retrieving you should convert the varbinary data to base64 string and base 64 string to image
string imageBase64Data = Convert.ToBase64String(img);
Here comes the important part the above code convert varbinary to base64string.It should be in proper format to display the image.Thats what the following code does
string imageDataURL = string.Format("data:image/png;base64,{0}", asd);
Session["Photo"] = imageDataURL;
Now you can able to view your image
Post the image from your client in a for of string, w/o specifying the type. On your action you can get the image in the following way :
var bytes = Convert.FromBase64String(yourStringHere);
using (var ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}

Categories

Resources