Home > Mobile >  How to redirect s3 link from rest controller java
How to redirect s3 link from rest controller java

Time:12-08

we have S3 storage ,there are a lot of some files, jpg,mp3 and others what i need to do? i need to redirect client to get the file from our s3 without uploading it on our server and i want that clien get the file on his pc with name and extension

so it looks like clien send us uuid - we find link of this file on s3 and redirect it like this

  @GetMapping("/test/{uuid}")
  public ResponseEntity<Void> getFile(@PathVariable UUID uuid) {
    var url = storageServiceS3.getUrl(uuid);
    try {
      var name = storageServiceS3.getName(uuid);
      return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY)
        .header(HttpHeaders.LOCATION, url)
        .header(HttpHeaders.CONTENT_TYPE, new MimetypesFileTypeMap().getContentType(name))
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="   name)
        .build();
    } catch (NoSuchKeyException ex) {
      return ResponseEntity.status(HttpStatus.NOT_FOUND)
        .build();
    }
  }

everything works good ,the file is downloading but one problem - the file has no name (its name still is key from s3) and no extension.

i think this code not works correctly

.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="   name)

is there any way to do this or i still need upload file to server and then send it to client ?

CodePudding user response:

@Алексеев станислав

Some work arround for this is consuming your rest service by javascript and add file's name in a new header response and rename file when download by client.

// don't forget to allow X-File-Name header on CORS in spring
headers.add("X-File-Name",  nameToBeDownloaded );

Example on ANGULAR but can be parsed to other language

this.http.get(uri_link_spring_redirecting_to_S3, {
    responseType: 'blob',
    observe: 'response'
}).subscribe(
    (response) => {
        var link = document.createElement('a');
        var file = new Blob([response.body], {
            type: 'text/csv;charset=utf-8;'
        });
        link.href = window.URL.createObjectURL(file);
        link.download = response?.headers?.get('X-File-Name');; 'download.csv';
        link.click();
    },
    error => {
        ...
    }
)

CodePudding user response:

Finally i found solution- i use S3Presigner ,make presigned url and redirect it with simple Http response

  @Bean
  public S3Presigner getS3Presigner() {
    return S3Presigner.builder()
      .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY)))
      .region(Region.of(REGION))
      .endpointOverride(URI.create(END_POINT))
      .build();
  }

  public String getPresignedURL(UUID uuid) {
    var name = getName(uuid);
    var contentDisposition = "attachment;filename="   name;
    var contentType = new MimetypesFileTypeMap().getContentType(name);

    GetObjectRequest getObjectRequest = GetObjectRequest.builder()
      .bucket(BUCKET)
      .key(uuid.toString())
      .responseContentDisposition(contentDisposition)
      .responseContentType(contentType)
      .build();

    GetObjectPresignRequest getObjectPresignRequest =
      GetObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(5))
        .getObjectRequest(getObjectRequest)
        .build();

    PresignedGetObjectRequest presignedGetObjectRequest =
      s3Presigner.presignGetObject(getObjectPresignRequest);

   return presignedGetObjectRequest.url().toString();
  }

@GetMapping("/redirect/{uuid}")
  public void redirectToS3(@PathVariable UUID uuid, HttpServletResponse response) {
    try {
      var URI = storageServiceS3.getPresignedURL(uuid);
      response.sendRedirect(URI);
    } catch (NoSuchKeyException | IOException e) {
      response.setStatus(404);
    }
  }

It works pretty good ;)

  • Related