Hi, I am trying to display an image from my backend to my ionic 5 app.
The request works in postman, my server returns a readablestream (using mongodb) with image/jpeg as header. But for my ionic app I am able to display it in ionic serve but when I try on real device its not displayed (it display the default icon’ broken image’ + image name). Here is the code I use in my dashboard.ts
my html : <div (click)="chooseAvatar()" class="bmjContainer inlineBlock"><a><ion-img [src]="userAvatar" alt="bitmojiLink" class="bmjLogo"></ion-img></a></div>
To store files / pictures / etc. is not the best practice in NoSQL.
I would suggest to use some external service as a storage.
Try to use FirebaseStorage it is quite easy to implelment into Ionic env.
Hi, could you precise what’s not the best practice ? and my whole backend is built in mongodb, I already use this bucket system to store musics and its working very fine, however for images I get this weird bug
It seems to me like you’re mysteriously reimplementing part of HTTP. What I would do instead of any of the blobbing or dataurling would be to have getUserAvatar return a URL - an actual https://my-backend-server/avatars/foobar0123.png sort of URL (or simply include this avatar URL as part of your User business interface). Then it can be passed directly through a bound parameter in an <img [src]="user.avatar">, and you let the browser do all the junk you’re trying to do manually - it’s better at it.
Now we’ve moved the problem to the backend, where your middleware server accepts requests to /avatars/:userid and sends back the same JPEG stream you’re sending now.
EDIT : here is my backend code (performing a get request through postman or my browser works but as I said above I dont know how to handle it in ionic)
async getUserAvatar(req, res) {
await user.findOne({ _id: req.decoded.id })
.then(result => {
let length = 0
try {
var avatarId = new ObjectID(result.avatarId)
} catch (err) {
return res.status(400).json({ message: "Invalid avatarID" });
}
db.collection('images.files').findOne({ _id: avatarId }, function (err, item) {
if (item) {
length = item.length;
}
if (err) {
return res.status(400).json({ message: "Invalid trackID in URL parameter. Must be a single String of 12 bytes or a string of 24 hex characters" });
}
res.set('content-type', 'image/jpeg');
res.set('accept-ranges', 'bytes');
res.set('content-length', JSON.stringify(length));
let bucket = new mongodb.GridFSBucket(db, {
bucketName: 'images'
});
let downloadStream = bucket.openDownloadStream(avatarId);
downloadStream.on('data', (chunk) => {
res.write(chunk);
});
downloadStream.on('error', () => {
res.sendStatus(404);
});
downloadStream.on('end', () => {
res.end();
});
});
})
.catch(err => {
res.status(500).json({ message: 'Error Occured finding user by id' });
});
}
Edit 2 : please dont mind the error message I return, I’m learning by myself and my code is not “clear” yet
Thank you guys for your answers, I understood my mistakes, I will first implement correctly my avatar request putting the http://…/myavatar.png in a variable, then put this variable as my source for my image tag. Then I will look for firebase cloud service or something to prepare when my app willl need to scale (hopefully )