Permettiamo agli utenti di caricare alcuni file di immagini sul nostro server web. Questi file non sono necessari 10-15 minuti dopo il caricamento. Esiste un modo per eliminare automaticamente questi file, ad es. tutti i file di immagine che hanno "scaduto" nel loro nome 15 minuti dopo la loro creazione?Come fare le pulizie in molo?
risposta
Io fondamentalmente configurazione scheduler quarzo dentro il mio webserver con un trigger cron
e il lavoro sembrava più o come questo
public static void deleteFilesOlderThanNdays(int daysBack, String dirWay, org.apache.commons.logging.Log log) {
File directory = new File(dirWay);
if(directory.exists()){
File[] listFiles = directory.listFiles();
long purgeTime = System.currentTimeMillis() - (daysBack * 24 * 60 * 60 * 1000);
for(File listFile : listFiles) {
if(listFile.lastModified() < purgeTime) {
if(!listFile.delete()) {
System.err.println("Unable to delete file: " + listFile);
}
}
}
} else {
log.warn("Files were not deleted, directory " + dirWay + " does'nt exist!");
}
}
ref: http://www.coderanch.com/t/384581/java/java/Delete-Files-Older-days
Non penso che il molo abbia una funzione integrata per questo. Si potrebbe creare una sorta di classe GarbageCollector e programmare la cancellazione di un file utilizzando un ScheduledExecutorService:
public class GarbageCollector {
private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
public void scheduleFileDeletion(Path path) {
service.schedule(() -> {
try {
Files.delete(path);
} catch (IOException ignored) {
}
}, 15, TimeUnit.MINUTES);
}
}
ci nulla di simile nel molo, come mlapeyre dice. Guarda Guavas cache.
Qualcosa del genere farà il trucco, credo:
Cache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(DELETE_FILES_LISTENER)
.build();
Hai appena risposto alla tua domanda - ottenere tutti i file con la parola "scade" nel nome e modificato 15 minuti prima ora e li elimina .
Ecco il codice. Non è efficiente ma semplice:
File dir=new File(".");
String []expiredFiles=dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return (name.contains("expired")&& new File(dir,name).lastModified()<System.currentTimeMillis()-15*60*1000);
}
});
for(String file:expiredFiles){
new File(dir,file).delete();
}
È possibile eseguirlo ogni 15 minuti o così. Oppure, approccio più semplice, eseguirlo quando ogni richiesta viene risposta e chiusa ma il thread non è ancora stato interrotto. Ad esempio quando subito dopo la chiusura del flusso di output sull'oggetto risposta. Non ci vogliono molte risorse, specialmente quando il thread è attivo e ancora in esecuzione.
In realtà dovresti eseguirlo come ogni minuto :) Basta creare un 'ServletContextListener' che gestirà il ciclo di vita di 'ScheduledExecutorService' e pianifica il tuo lavoro di pulizia da eseguire ogni minuto. –
Creare una classe modello per memorizzare informazioni sul caricamento di immagini come, imagePath
e uploadedTime
.
class UploadedImage {
private Path imagePath;
private long uploadedTime;
public UploadedImage(Path imagePath, long uploadedTime) {
this.imagePath = imagePath;
this.uploadedTime = uploadedTime;
}
public Path getImagePath() {
return imagePath;
}
public long getUploadedTime() {
return uploadedTime;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UploadedImage other = (UploadedImage) obj;
if (!Objects.equals(this.imagePath, other.imagePath)) {
return false;
}
if (this.uploadedTime != other.uploadedTime) {
return false;
}
return true;
}
}
Creare un oggetto UploadedImage per ogni immagine-caricando, e memorizzarli in un ArrayList globale.
//...
ArrayList<UploadedImage> imageBucket = new ArrayList<>();
//...
public synchronized void uploadingImage(Path imagePath, long uploadedTime){
imageBucket.add(new UploadeImage(imagePath, uploadedTime));
}
E preparare un thread per eseguire la cancellazione dei file come segue.
boolean deletionOff = false;
new Thread(new Runnable() {
private final long IMAGE_LIFE_TIME = 1000 * 60 * 15;//fifteen minutes
@Override
public void run() {
while (!deletionOff) {
//this fore-each will retrieve objects from OLDEST to NEWEST
for (UploadedImage uploadedImage : imageBucket) {
//finds the elapsed time since the upload of this image
long timeElapsed = System.currentTimeMillis() - uploadedImage.getUploadedTime();
if (timeElapsed >= IMAGE_LIFE_TIME) {
//following commands will execute only if the image is eligible to delete
try {
Files.delete(uploadedImage.getImagePath());
} catch (IOException ex) {
//
} finally {
imageBucket.remove(uploadedImage);
}
} else {
//this block will execute when IMAGE_LIFE_TIME is
//bigger than the elapsed time which means the
//selected image only have
//(IMAGE_LIFE_TIME - timeElapsed) of time to stay alive
//NOTE :
//there is no need to check the next UploadedImage
//objects as they were added to the list after the
//currently considering UploadedImage object,
//which is still has some time to stay alive
try {
Thread.sleep(IMAGE_LIFE_TIME - timeElapsed);
break;
} catch (InterruptedException ex) {
//
}
}
}
}
}
}).start();
perché non utilizzare una cache e memorizzare i byte dell'immagine direttamente nella cache. Imposta un tempo di sfratto/scadenza in scrittura (non accesso) di 10-15 minuti e la cache si occupa automaticamente dell'immagine. Qualsiasi ricerca per l'immagine riceve risposta direttamente dalla cache (purché la voce non sia scaduta) –