So I have this array with different links
const urls = ['myurl.com', 'localhost.com'... etc]
In the for loop I want to create an object like so, it should basically create a new object for every URL, and then pass the looped URL to the userUrl section
for(let url of urls) {
[
{
user: 1,
isVerified: true
userUrl: url
}
]
}
After the loop finishes, this data should be readable in a JSON file
it should look something like this
[
{
user: 1,
isVerified: true,
userUrl: myUrl.com
},
{
user: 2,
isVerified: true,
userUrl: localhost.com
}
...etc
]
I tried this code on Chrome and it works correctly plus it correctly format the json data now, instructing JSON.stringify to use 4 spaces indentation.
It won't work in the snippet, but it will if you save it in your own file. I did it inside the chrome developer tools in the Sources tab as a snippet and as soon as executed the download queue was fed with the json file.
I left the live snippet here because there's the chance to see the jsonData on console anyway.
The way to programmatically send a string to a download file was inspired by this question:
How do I save JSON to local text file
function download(content, fileName, contentType) {
var a = document.createElement("a");
var file = new Blob([content], {type: contentType});
a.href = URL.createObjectURL(file);
a.download = fileName;
a.click();
}
const urls = ['myurl.com', 'localhost.com'];
const data = factory(urls);
const jsonData = JSON.stringify(data, null, 4);
console.log(jsonData);
download(jsonData, 'json.txt', 'text/plain');
function factory(urls){
const output = [];
for(let url of urls) {
output.push({
user: 1,
isVerified: true,
userUrl: url
});
}
return output;
}
Related
I am currently having a few methods in the following where handlePdfBlob handles fileType that are in "pdf" while the rest are for other file types where the blob data will be downloaded using handleBlob method. I would like to have a seperate method for fileType that are in "mp4" where the video is not downloaded but being played in the same HTML page upon clicking on a button. I have look at the HTMLVideoElement but I am not sure how am I able to assign the blob data object that is given in the response body of the API to the HTMLVideoElement "video" tag in the HTML file. What are some suggested ways that I am able to achieve playing the video directly in the HTML page after making the API calling from the HTML page?
downloadSampleFile(apiUrl: string, fileName: string, fileType: string, req: any = {}): void {
const options = createRequestOption(req);
this.http.get<Blob>(apiUrl, { params: options, observe: 'response', responseType: 'blob' as 'json' })
.subscribe(((res: HttpResponse<Blob>) => {
if (fileType.match("pdf")) {
this.handlePdfBlob(res.body!, fileName, fileType);
}
else {
this.handleBlob(res.body!, fileName, fileType);
}
}));
}
private handlePdfBlob(data: Blob, fileName: string, fileType: string): void {
const blob = new Blob([data], { type: 'application/pdf' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
private handleBlob(data: Blob, fileName: string, fileType: string): void {
const blob = new Blob([data], { type: 'application/octet-stream' });
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.download = fileName + "." + fileType;
anchor.href = url;
anchor.click();
}
I have tried to create a new method for this and return the URL string.
const url = window.URL.createObjectURL(blob);
However, I am not sure why the url is returning undefined in the console.
I want to save received base64 string in mysql table in a BLOB field. I have used sequelize version 5 as my ORM and the model is defined as follows.
sequelize.define('PLAYER', {
player_id: {
primaryKey: true,
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true
},
player_name: DataTypes.STRING,
player_image: {
type: DataTypes.BLOB('medium'),
get () {
let data = this.getDataValue('player_image');
return data ? data.toString('base64') : '';
}
}
}
In my put method,
db.PLAYER.findByPk(req.params.playerId).then((player)=>{
if (req.body.player_image) {
const base64 = req.body.player_image.replace(/^data:image\/[a-z]+;base64,/, "");
const blob = b64toBlob(base64, 'image/jpeg');
player.player_image = blob;
}
player.player_name = req.body.player_name;
player.save().then(() => {
res.status(200).json(player);
}).catch(function (err) {
return next(err);
});
});
For Base64 to Blob conversion.
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
}
A blob is saving in the table but my response body is as follows. I have converted BLOB to base64 before sending the response.
{
"player_id": 1032,
"player_name": "Oliver Driscoll",
"player_image": "[object Blob]"
}
Which means the saved blob is actually "[object Blob]". Not the image.
The received base64 (req.body.player_image) for the end point is confirmed as correct. I am running out of time and don't know what to do as this is the requirement (Saving the image as blob).
I Know, this is a old issue. But i had this same problem, and after so many tries, i was able to solve it. So, if anyone have this problem in the future, i will let my solution here:
In my case i was able to get a Blob already, from a fetch response.
So i have in my code like this:
await fetch(imageUrl)
.then(async (response) => {
// GET Blob Object from response; can use response.arrayBuffer() directly too
let myBlobImg = await response.blob();
// Convert Blob.ArrayBUffer to a Buffer
let myBufferImg = Buffer.from(await myBlobImg.arrayBuffer());
})
Then i just save myBufferImg on DB, as a Buffer. In your case #silent_27 could be
player.player_image = Buffer.from(await myBlobImg.arrayBuffer());
I'm using SQlite3 DataBase on NodeJS with sqlite3^5.0.1 package.
I save like this on my dataBase and works fine. I've tried save like myBlobImg.text();. But this away, i was not able to load on a <img src={}> html tag in my application.
If anyone need to know, to show this BLOB on a <img> HTML, i just do a get on my DB to get my ProductObject and convert to a base64 image:
// imageData is the Buffer saved on BD. imageData.data is an Array from Buffer
let imgBase64 = Buffer.from(product.productImage.imageData.data).toString('base64');
imgBase64 = `data:image/jpeg;base64,${imgBase64}`;
//....
<img src={imgBase64}>
I Had to use Buffer.from again otherwhise if i just use like
let imgBase64 = product.productImage.imageData.toString('base64');
the imgBase64 would be "[Object ojbect]
Two part quersion.
Part 1:
Im uploading an image to my server and want to save it to my database.
So far:
table:
resolver:
registerPhoto: inSequence([
async (obj, { file }) => {
const { filename, mimetype, createReadStream } = await file;
const stream = createReadStream();
const t = await db.images.create({
Name: 'test',
imageData: stream ,
});
},
])
executing query:
Executing (default): INSERT INTO `images` (`Id`,`imageData`,`Name`) VALUES (DEFAULT,?,?);
But nothing is saved.
Im new to this and im probably missing something but dont know what.
Part2:
This is followed by part 1, lets say I manage to save the image, how do I read it and send it back to my FE?
An edit: Ive read alot of guides saving the an image name to the db and then tha actuall image in a folder. This is NOT what im after, want to save the image to the DB and then be able to fetch it from the DB abd present it.
This took me some time but I finaly figured it out.
First step (saving to the db):
Have to get the entire stream data and read it like this:
export const readStream = async (stream, encoding = 'utf8') => {
stream.setEncoding('base64');
return new Promise((resolve, reject) => {
let data = '';
// eslint-disable-next-line no-return-assign
stream.on('data', chunk => (data += chunk));
stream.on('end', () => resolve(data));
stream.on('error', error => reject(error));
});
};
use like this:
const streamData = await readStream(stream);
Before saving I tur the stream into a buffer:
const buff = Buffer.from(streamData);
Finaly the save part:
db.images.create(
{
Name: filename,
imageData: buff,
Length: stream.bytesRead,
Type: mimetype,
},
{ transaction: param }
);
Note that I added Length and Type parameter, this is needed if you like to return a stream when you return the image.
Step 2 (Retrieving the image).
As #xadm said multiple times you can not return an image from GRAPHQL and after some time I had to accept that fact, hopefully graphql will remedy this in the future.
S What I needed to do is set up a route on my fastify backend, send a image Id to this route, fetch the image and then return it.
I had a few diffirent approaches to this but in the end I simpy returned a binary and on the fronted I encoded it to base64.
Backend part:
const handler = async (req, reply) => {
const p: postParams = req.params;
const parser = uuIdParserT();
const img = await db.images.findByPk(parser.setValueAsBIN(p.id));
const binary = img.dataValues.imageData.toString('binary');
const b = Buffer.from(binary);
const myStream = new Readable({
read() {
this.push(Buffer.from(binary));
this.push(null);
},
});
reply.send(myStream);
};
export default (server: FastifyInstance) =>
server.get<null, any>('/:id', opts, handler);
Frontend part:
useEffect(() => {
// axiosState is the obj that holds the image
if (!axiosState.loading && axiosState.data) {
// #ts-ignore
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
// #ts-ignore
// eslint-disable-next-line no-plusplus
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
};
const blob = b64toBlob(axiosState.data, 'image/jpg');
const urlCreator = window.URL || window.webkitURL;
const imageUrl = urlCreator.createObjectURL(blob);
setimgUpl(imageUrl);
}
}, [axiosState]);
and finaly in the html:
<img src={imgUpl} alt="NO" className="imageUpload" />
OTHER:
For anyone who is attempting the same NOTE that this is not a best practice thing to do.
Almost every article I found saved the images on the sever and save an image Id and other metadata in the datbase. For the exact pros and cons for this I have found the following helpful:
Storing Images in DB - Yea or Nay?
I was focusing on finding out how to do it if for some reason I want to save an image in the datbase and finaly solved it.
There are two ways to store images in your SQL database. You either store the actual image on your server and save the image path inside your mySql db OR you create a BLOB using the image and store it in db.
Here is a handy read https://www.technicalkeeda.com/nodejs-tutorials/nodejs-store-image-into-mysql-database
you should save the image in a directory and save the link of this image in the database
I am using the package below to try to convert uploaded excel files (.xlsx) to JSON files on my Express web application:
https://www.npmjs.com/package/xlsx-to-json
So here is my form for the user to upload:
form(id = "form1", action="/upload", method="post", enctype="multipart/form-data")
input(type="file", id="control", name="XLupload")
br
input(type="submit" value="Upload" name="Submit")
and here is my routing for the upload back in my main express (app.js) file:
var multer = require('multer');
var upload = multer({dest: './uploads'});
var excel_upload = upload.single('XLupload');
app.post('/upload', excel_upload, function(req, res) {
var fileObject = req.file;
var filePath = fileObject.path;
/*** This is what the file Object looks like when uploaded:
{ fieldname: 'XLupload',
originalname: 'testing.xlsx',
encoding: '7bit',
mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
destination: './uploads',
filename: 'c1d55ea7d1f6fccc7e3d3d2764db8881',
path: 'uploads\\c1d55ea7d1f6fccc7e3d3d2764db8881',
size: 8013 }
***/
xlsxj({
input: String(filePath),
output: "output.json"
}, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
});
anyways, to put it shortly, the uploads seem to work fine, that is, they are uploaded to the /uploads folder in the directory. However, the JSON file that I get back from the xlsxj converter is empty and I'm not sure why. I made a small test xlsx file with some words in random cells and it still game me back an empty
[]
in output.json. Anybody can let me know what I am doing wrong?
You can try to use this library XLSX (https://github.com/SheetJS/js-xlsx) and add this code after get workssheet
var roa = XLSX.utils.sheet_to_row_object_array(worksheet);
I am trying to do a file upload using angularjs, using angular-file-upload library (https://github.com/danialfarid/angular-file-upload)
Here is my code
// ===============================My HTML File===========================
<input type="file" ng-file-select="onFileSelect($files)">
// ===============================My Controller==========================
var $scope.formObj = {
name: "Test"
};
var fileToUpload;
$scope.onFileSelect = function (file) {
fileToUpload = file[0];
};
// POSt request to /api/items
$scope.addItem = function() {
console.log($scope.formObj);
$scope.upload = $upload.upload({
url: '/api/items',
method: 'POST',
data: { myObj: $scope.formObj },
file: fileToUpload
}).success(function(data, status, headers, config) {
console.log("success");
});
};
// ================================My Backend=============================
// This is the function that will receive POST request to /api/items
exports.create = function(req, res) {
console.log(req.body); // req.body is just an empty object. ==> {}
// apparently, I found all the data to be in req._readableState.buffer[0]
// in the form of a buffer
var buffer = req._readableState.buffer[0];
// trying to console.log the buffer.toString, resulting in something similar to this
// { name: "Test", image: Object }
console.log(buffer.toString());
return res.send(200);
};
So my backend received the formObj with all its properties and values, however, the actual file data itself, whether in the form of buffer, or base64, or whatever, never gets received.
I wonder why. This is my first time working with file uploading, so I don't understand the concept.
Please point me in the right direction
If you are using Latest version of Express, you'd notice that
app.use(express.multipart()); is no longer bundled with express.
So do the following configuration changes. in express.js
var multer = require('multer');
app.use(multer({ dest: './uploads/'}));
You'd find that after doing this you would find the data and file , in req.body req.file respectively.
Hope it helps