Возврат файла из Google Cloud Storage через REST API без предварительной загрузки локально

Мы хотели бы иметь Java REST API для возврата файлов из облачного хранилища Google в виде вложений. Я смог заставить его работать, используя следующий метод. Проблема в том, что файл должен быть загружен локально в контейнер службы (мы развертываем его в Google Cloud Run), и это проблема в случае очень больших файлов и, как правило, может быть плохой практикой. Есть ли способ как-то изменить этот код, чтобы пропустить создание локального файла?

@GetMapping(path = "/file", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<InputStreamResource> getSpecificFile(@RequestParam String fileName,
        @RequestParam String bucketName, @RequestParam String projectName) {
    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    Blob blob = storage.get(bucketName, fileName);
    ReadChannel readChannel = blob.reader();
    String outputFileName = tempFileDestination.concat("\\").concat(fileName);
    try (FileOutputStream fileOutputStream = new FileOutputStream(outputFileName)) {
        fileOutputStream.getChannel().transferFrom(readChannel, 0, Long.MAX_VALUE);
        String contentType = Files.probeContentType(Paths.get(outputFileName));

        FileInputStream fileInputStream = new FileInputStream(outputFileName);
        return ResponseEntity.ok().contentType(MediaType.valueOf(contentType))
                .header("Content-Disposition", "attachment; filename = " + fileName)
                .body(new InputStreamResource(fileInputStream));
    } catch (IOException e) {
        e.printStackTrace();
        return ResponseEntity.internalServerError().body(null);
    } finally {
        // delete the local file as cleanup
        try {
            Files.delete(Paths.get(outputFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, это мне не потребовалось много времени, чтобы понять. Я смог заставить его работать следующим образом:

@GetMapping(path = "/file", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<InputStreamResource> getSpecificFile(@RequestParam String fileName, @RequestParam String bucketName, @RequestParam String projectName) {
    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    Blob blob = storage.get(bucketName, fileName);
    ReadChannel readChannel = blob.reader();
    try {
        String contentType = Files.probeContentType(Paths.get(fileName));

        InputStream inputStream = Channels.newInputStream(readChannel);
        return ResponseEntity.ok().contentType(MediaType.valueOf(contentType))
                .header("Content-Disposition", "attachment; filename = " + fileName)
                .body(new InputStreamResource(inputStream));
    } catch (IOException e) {
        e.printStackTrace();
        return ResponseEntity.internalServerError().body(null);
    }
}

В основном перенаправьте InputStream в readChannel вместо файла.

Другие вопросы по теме