Невозможно удалить файл, если он является аргументом

Сначала я поставлю свой код:

@Post
public Representation post(InputStream zip) throws Throwable {
    createFile(zip, "C:/temp\abc.zip");
    return new StringRepresentation("File uploaded");
}    

public void createFile(InputStream zipStream, uploadedFileLocation) throws Exception {
    try {
        writeToFile(zipStream, uploadedFileLocation);
        FileUtils.forceDelete(new File(uploadedFileLocation));
        } catch (Exception e) {
             throw e;
        }
}


private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) {
    try {
        OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
        int read = 0;
        byte[] bytes = new byte[1024];

        out = new FileOutputStream(new File(uploadedFileLocation));
        while ((read = uploadedInputStream.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.flush();
        out.close();
        uploadedInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Я пытаюсь создать сервер, который позволяет пользователю загружать zip-файл. Затем сервер записывает zip-файл на диск, распаковывает его, затем удаляет zip-архив, сохраняя при этом разархивированную часть на сервере. Однако, когда я отправляю zip-файл на свой сервер, он не может быть удален. При использовании FileUtils.forceDelete() пишет, что не может удалить файл. Идеально, когда zip удаляется после распаковки.

РЕДАКТИРОВАТЬ: я могу удалить файл только после того, как post(InputStream zip) вернется. Если я вызову удаление из метода post, оно не будет удалено, потому что сообщение не вернулось. Есть ли способ обойти это?


person Stephen D    schedule 01.08.2013    source источник


Ответы (4)


<страйк>Хм. Похоже, вы пытаетесь удалить каталог?

FileUtils.forceDelete(new File(uploadedFileLocation));

Но uploadedFileLocation - это "C:\temp" из вашего метода post. Я не уверен, вызовет ли это проблему или это задуманное поведение, но этот код не удаляет zip-файл и пытается удалить фактический каталог C:\temp.

Кроме того, потенциально стоит отметить: в вашем методе writeToFile вы дважды инициализируете OutputStream out. Я не уверен в этом на 100%, но может случиться так, что первая инициализация удерживает указатель файла открытым до тех пор, пока весь объект не будет удален из стека (т. е. когда post вернется). Выньте вторую инициализацию и посмотрите, происходят ли какие-либо изменения?

person Deactivator2    schedule 01.08.2013
comment
Извините, случайно пропустил. Теперь там есть имя файла. C:/temp/abc.zip - person Stephen D; 01.08.2013
comment
В этом случае я все еще склоняюсь к потоку вывода с двойной инициализацией, который потенциально удерживает файл в этом месте открытым до тех пор, пока объект не выйдет из стека. Я не знаком с библиотекой FileUtils, но знаю, что класс java.io.File имеет собственную функцию удаления. Возможно, если первый способ не работает, попробуйте new File(fileUploadLocation).delete(). Кроме того, вы получаете сообщение об исключении, когда оно терпит неудачу? Если да, то можете ли вы добавить его в свой пост? - person Deactivator2; 01.08.2013
comment
Оказывается, я должен был вызвать file.delete(); вместо использования FileUtils. - person Stephen D; 01.08.2013

Я предполагаю, что ваша проблема может быть вызвана тем, что вы используете «C:/temp» вместо «C:/temp/fileName», поэтому в конечном итоге вы пытаетесь удалить папку, на которую у вас может не быть разрешений.

person Ale Zalazar    schedule 01.08.2013

Вам не нужно использовать местоположение файла, почему бы не использовать фактический файл? Передайте файл в качестве аргумента и выполните file.delete();, когда закончите.

person Lai    schedule 01.08.2013

Если проблема не в том, что вы пытаетесь удалить каталог, то, скорее всего, файл, который вы пытаетесь удалить, все еще открыт. В Windows это означает, что вы не сможете удалить файл.

Судя по всему, ваш метод writeToFile дважды открывает файл... но закрывает его только один раз. Я подозреваю, что это означает утечку дескриптора файла, и ОС будет думать, что приложение все еще использует файл.


Оказывается, я должен был вызвать file.delete(); вместо использования FileUtils.

Я так не думаю. Конечно, вы не получите исключение из-за того, что файл не был удален. Но вместо этого File.delete() вернет false, и ваше приложение оставит файл в файловой системе. В долгосрочной перспективе это может быть хуже, если у вас нет другого средства для очистки потерянных файлов.

person Stephen C    schedule 01.08.2013