I am using MvvmCross 3.1.1 and MvxImageView on iOS.
The MvxImageView load images from Urls and cache these. However, I want to update these images but it keeps loading the cached image.
I.e. when using Url like www.lalalalalala.dk/bjar.png. Then this image is updated from somewhere else. However the Url stays the same. It seems that the MvxImageView keeps the cached image and do not load the new one.
Is it possible to remove the cached image and force it to reload the image from the Url?
I tried taking a look at
var service = Mvx.Resolve<IMvxImageHelper<UIImage>>();
but I could not find anything useful.
UPDATE
I must say this gives me a bit of a headache. I found how to remove a image from the filesystem, however sometimes the image is stored in memory and therefore cannot be deleted. Any suggestions how to tackle that situation?
I ended up extending (copy/paste) the image-cache - MvxImageCache and IMvxImageCache in mvvmcross and added these two methods.
public void RemoveUrlFromCache(string url)
{
this.RunSyncOrAsyncWithLock(
() =>
{
Entry entry;
if (this._entriesByHttpUrl.TryGetValue(url, out entry))
{
this._entriesByHttpUrl.Remove(url);
}
this._fileDownloadCache.RequestLocalFilePath(url, (stream) => this.DeleteFile(url, stream),
(exception) => this.ProcessError(url, exception));
});
}
private void DeleteFile(string url, string filepath)
{
if (!string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(filepath))
{
var fileService = Mvx.Resolve<IMvxFileStore>();
fileService.DeleteFile(filepath);
}
}
With This I am able to call the following in my subclassed Imageview in droid(touch is similar).
var cache = Mvx.Resolve<IMvxImageCache<Bitmap>>() as ImageCache<Bitmap>;;
if (cache != null)
{
cache.RemoveUrlFromCache(_imageUrl);
}
I will do a pull request and hopefully they will take it in or do something similar
Related
Is there a way to write urls in html, but get the image from db instead of a folder?
my goal is :
HTML (img.path is some url)
<img src={{img.path}}>
ts (as example):
getImage(String : url) {
getFileFromDb(url);
return image;
}
I'm trying to make a angular project using lots of images. For front-end, I know there two ways to get a image, using html (login.html):
<img src='assets/img/loginBanner.jpg'>
or using db (loginBanner.ts):
reader.readAsDataURL(blob);
reader.onload = () => {
img.readerResult = reader.result;
img.blob = blob;
};
Unforturnatly, these two both have disadvantages
There's tons of images we'll use, it's not probable to put all of it in "assets/img" folder.
But if using db, we have to send all the images everytime, that seems like a waste on the boardband.
when reading BOOKS on scribd.com the download functionality is not enabled. even browsing through the html source code I was unable to download the actual book. Great stuff ... but HOW did they do this ?
I am looking to implement something similar, to display a pdf (or converted from pdf) in such a way that the visitor cannot download the file
Most solutions I have seen are based on obfusticating the url.. but with a little effort people can find the url and download the file. ScribD seems to have covered this quite well..
Any suggestions , ideas how to implement such a download protection ?
It actually works dinamically building the HTML based on AJAX requests made while you're flipping pages. It is not image based. That's why you're finding it difficult to download the content.
However, it is not that safe for now. I present a solution below to download books that is working today (27th Jan 2020) not for teaching you how to do that (it is not legal), but to show you how you should prevent (or, at least, making it harder) users from downloading content if you're building something similar.
If you have a paid account and open the book page (the one that opens when you click 'Start Reading'), you can download an image of each book page by loading a library such as dom-to-image.
For instance, you could load the library using the developer tools (all code shown below must be typed in the page console):
if (injectDomToImage == undefined) {
var injectDomToImage = document.createElement('script');
injectDomToImage.src = "https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js";
document.getElementsByTagName('head')[0].appendChild(injectDomToImage);
}
And then, you could define functions such as these:
function downloadPage(page, prefix) {
domtoimage.toJpeg(document.getElementsByClassName('reader_and_banner_container')[0], {
quality: 1,
})
.then(function(dataUrl) {
var link = document.createElement('a');
link.download = `${prefix}_page_${page}.jpg`;
link.href = dataUrl;
link.click();
nextPage(page, prefix);
});
}
function checkPageChanged(page, oldPageCounter, prefix) {
let newPageCounter = $('.page_counter').html();
if (oldPageCounter === newPageCounter) {
setTimeout(function() {
checkPageChanged(page, oldPageCounter, prefix);
}, 500);
} else {
setTimeout(function() {
downloadPage(page + 1, prefix);
}, 500);
}
}
function nextPage(page, prefix) {
let oldPageCounter = $('.page_counter').html();
$('.next_btn').trigger('click');
// Wait until page counter has changed (page loading has finished).
checkPageChanged(page + 1, oldPageCounter, prefix);
}
function download(prefix) {
downloadPage(1, prefix);
}
Finally, you could download each book page as a JPG image using:
download('test_');
It will download each page as test_page_.jpg
In order to prevent such type of 'robot', they could, for example, have used Re-CAPTCHA v3 that works in background seeking for 'robot'-like behaviour.
I've been working on a small twitter-like website to teach myself React. It's going fairly well, and i want to allow users to take photos and attach it to their posts. I found a library called React-Camera that seems to do what i want it do to - it brings up the camera and manages to save something.
I say something because i am very confused about what to actually -do- with what i save. This is the client-side code for the image capturing, which i basically just copied from the documentation:
takePicture() {
try {
this.camera.capture()
.then(blob => {
this.setState({
show_camera: "none",
image: URL.createObjectURL(blob)
})
console.log(this.state);
this.img.src = URL.createObjectURL(blob);
this.img.onload = () => { URL.revokeObjectURL(this.src); }
var details = {
'img': this.img.src,
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch('/newimage', {
method: 'post',
headers: {'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8'},
body: formBody
});
console.log("Reqd post")
But what am i actually saving here? For testing i tried adding an image to the site and setting src={this.state.img} but that doesn't work. I can store this blob (which looks like, for example, blob:http://localhost:4000/dacf7a61-f8a7-484f-adf3-d28d369ae8db)
or the image itself into my DB, but again the problem is im not sure what the correct way to go about this is.
Basically, what i want to do is this:
1. Grab a picture using React-Camera
2. Send this in a post to /newimage
3. The image will then - in some form - be stored in the database
4. Later, a client may request an image that will be part of a post (ie. a tweet can have an image). This will then display the image on the website.
Any help would be greatly appreciated as i feel i am just getting more confused the more libraries i look at!
From your question i came to know that you are storing image in DB itself.
If my understanding is correct then you are attempting a bad approcah.
For this
you need to store images in project directory using your node application.
need to store path of images in DB.
using these path you can fetch the images and can display on webpage.
for uploading image using nodejs you can use Multer package.
I have a small webapp built with nodejs and express (among other things) that has a route to resize images on the fly (using sharp). The route looks like this:
router.get('/image/:options/:basedir/:dir/:img', utilitiesController.getOptimizedImage);
In the utilities controller, I have the getOptimizedImage function checking for the existing image, returning the existing image content if it exists, or if it doesn't, performing some image processing tasks, then returning the resulting image.
exports.getOptimizedImage = async (req, res) => {
// Parse options from request...
// first, check to see if resized version exists
fs.readFile(processedImgPath, function (err, processedImg) {
if (err) {
//console.log('File does not yet exist.');
// If resized version doesn't exist, check for original
fs.readFile(originImgPath, function (err, originImg) {
if (err) {
// If origin image doesn't exist, return 400.
} else if (w || h) {
// If origin image does exist, process it...
// Once it's processed, return the processed image
res.end(newImg);
return;
}
}
} else {
//
res.end(processedImg);
//res.redirect(existingFileUrl);
return;
}
}
}
This code works. I can request something like so:
<img src="http://example.com/image/w800/foo/bar/imagename.jpg">
...and it returns the resized image as expected. The issue seems to be that because of the way the image is returned using res.end(), the browser cache (testing in Chrome) doesn't ever store the image, so reloading the page downloads the image fresh instead of loading it from memory or disk.
I can alternatively use res.redirect() to send back the url of the existing processed image file, which will be cached on refresh, but that feels like the wrong way to do this, since it ultimately doubles all the image requests using the image processing path.
I don't want to process the images prior to request; I'm specifically looking to only process the images the first time they're requested, then store a processed version to reference each consecutive time. I'm open to alternatives within these constraints, but hoping someone can explain how I might leverage browser caching with my current structure?
You should add http headers for caching before any res.end, the example below will set the Expires time to 1 day (86400000ms).
res.set({
"Cache-Control": "public, max-age=86400",
"Expires": new Date(Date.now() + 86400000).toUTCString()
})
So i see this code on the Docs
Template.myForm.events({
'change .myFileInput': function(event, template) {
FS.Utility.eachFile(event, function(file) {
Images.insert(file, function (err, fileObj) {
//Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
});
});
}
});
But i dont want the file upload inmediatly when i click "myFileInptu" , i want to store that value (from the input), and insert lately with a button, so there is some way to do this?
Also its there a way to upload a FSCollection without a file? just metadata
Sorry for bad english hope you can help me
Achieving what you want to requires a trivial change of the event, i.e switching from change .myFileInput to submit .myForm. In the submit event, you can get the value of the file by selecting the file input, and then storing it as a FS File manually. Something like:
'submit .myForm': function (event, template) {
event.preventDefault();
var file = template.find('#input').files[0];
file = new FS.File(file);
// set metadata
file.metadata = { 'caption': 'wow' };
Images.insert(file, function (error, file) {
if (!error)
// do something with file._id
});
}
If you're using autoform with CollectionFS, you can put that code inside the onSubmit hook. The loop you provided in your question works also.
As for your second question, I don't think FS.Files can be created without a size, so my guess is no, you can't just store metadata without attaching it to a file. Anyways, it seems to me kind of counterintuitive to store just metadata when the metadata is supposed to describe the associated image. You would be better off using a separate collection for that.
Hope that helped :)