Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 650 Vote(s) - 3.58 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Downloading a file from spring controllers

#11
If it helps anyone. You can do what the accepted answer by Infeligo has suggested but just put this extra bit in the code for a forced download.

response.setContentType("application/force-download");
Reply

#12
This can be a useful answer.

[To see links please register here]


Extending to this, adding content-disposition as an attachment(default) will download the file. If you want to view it, you need to set it to inline.
Reply

#13
In my case I'm generating some file on demand, so also url has to be generated.

For me works something like that:

@RequestMapping(value = "/files/{filename:.+}", method = RequestMethod.GET, produces = "text/csv")
@ResponseBody
public FileSystemResource getFile(@PathVariable String filename) {
String path = dataProvider.getFullPath(filename);
return new FileSystemResource(new File(path));
}

Very important is mime type in `produces` and also that, that name of the file is a part of the link so you has to use `@PathVariable`.

HTML code looks like that:

<a th:href="@{|/dbreport/files/${file_name}|}">Download</a>

Where `${file_name}` is generated by Thymeleaf in controller and is i.e.: result_20200225.csv, so that whole url behing link is: `example.com/aplication/dbreport/files/result_20200225.csv`.

After clicking on link browser asks me what to do with file - save or open.
Reply

#14
If you:

- Don't want to load the whole file into a `byte[]` before sending to the response;
- Want/need to send/download it via `InputStream`;
- Want to have full control of the Mime Type and file name sent;
- Have other `@ControllerAdvice` picking up exceptions for you (or not).

The code below is what you need:

@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity<FileSystemResource> downloadStuff(@PathVariable int stuffId)
throws IOException {
String fullPath = stuffService.figureOutFileNameFor(stuffId);
File file = new File(fullPath);
long fileLength = file.length(); // this is ok, but see note below

HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType("application/pdf");
respHeaders.setContentLength(fileLength);
respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");

return new ResponseEntity<FileSystemResource>(
new FileSystemResource(file), respHeaders, HttpStatus.OK
);
}


**More on `setContentLength()`:** First of all, the [`content-length` header is optional per the HTTP 1.1 RFC][1]. Still, if you can provide a value, it is better. To obtain such value, know that `File#length()` should be good enough in the general case, so it is a safe default choice.<br>
In very specific scenarios, though, it [can be slow][2], in which case you should have it stored previously (e.g. in the DB), not calculated on the fly. Slow scenarios include: if the file is _very_ large, specially if it is on a remote system or something more elaborated like that - a database, maybe.

---

<br>

### `InputStreamResource`

If your resource is not a file, e.g. you pick the data up from the DB, you should use [`InputStreamResource`][3]. Example:

InputStreamResource isr = new InputStreamResource(...);
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#15
I had to add this to download any file

response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+"file.txt");
all code:

@Controller
public class FileController {

@RequestMapping(value = "/file", method =RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(HttpServletResponse response) {

final File file = new File("file.txt");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+"file.txt");
return new FileSystemResource(file);
}
}
Reply

#16
### Do

1. Return `ResponseEntity<Resource>` from a handler method
1. Specify `Content-Type`
1. Set `Content-Disposition` if necessary:
1. filename
1. type
1. [`inline`](

[To see links please register here]

) to force preview in a browser
1. [`attachment`](

[To see links please register here]

) to force a download

### Example

```java
@Controller
public class DownloadController {
@GetMapping("/downloadPdf.pdf")
// 1.
public ResponseEntity<Resource> downloadPdf() {
FileSystemResource resource = new FileSystemResource("/home/caco3/Downloads/JMC_Tutorial.pdf");
// 2.
MediaType mediaType = MediaTypeFactory
.getMediaType(resource)
.orElse(MediaType.APPLICATION_OCTET_STREAM);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
// 3
ContentDisposition disposition = ContentDisposition
// 3.2
.inline() // or .attachment()
// 3.1
.filename(resource.getFilename())
.build();
headers.setContentDisposition(disposition);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
}
```

### Explanation

**Return `ResponseEntity<Resource>`**

When you return a [`ResponseEntity<Resource>`](

[To see links please register here]

), the [`ResourceHttpMessageConverter`](

[To see links please register here]

) writes file contents

Examples of `Resource` implementations:

* [`ByteArrayResource`](

[To see links please register here]

) - based in `byte[]`
* [`FileSystemResource`](

[To see links please register here]

) - for a `File` or a `Path`
* [`UrlResource`](

[To see links please register here]

) - retrieved from `java.net.URL`
* [`GridFsResource`](

[To see links please register here]

) - a blob stored in MongoDB
* [`ClassPathResource`](

[To see links please register here]

) - for files in classpath, for example files from `resources` directory. [My answer to question "Read file from resources folder in Spring Boot"](

[To see links please register here]

) explains how to locate the resource in classpath in details

**Specify `Content-Type` explicitly**:

_Reason: see "[FileSystemResource is returned with content type json](

[To see links please register here]

; question_


Options:

* Hardcode the header
* Use the [`MediaTypeFactory`](

[To see links please register here]

) from Spring. The `MediaTypeFactory` maps `Resource` to `MediaType` using the `/org/springframework/http/mime.types` file
* Use a third party library like [Apache Tika](

[To see links please register here]

)

**Set `Content-Disposition` if necessary**:

About [`Content-Disposition`](

[To see links please register here]

) header:

> The first parameter in the HTTP context is either `inline` (default value, indicating it can be displayed inside the Web page, or as the Web page) or `attachment` (indicating it should be downloaded; most browsers presenting a 'Save as' dialog, prefilled with the value of the filename parameters if present).

Use [`ContentDisposition`](

[To see links please register here]

) in application:

* To *preview* a file in a browser:
```java
ContentDisposition disposition = ContentDisposition
.inline()
.filename(resource.getFilename())
.build();
```

* To force a *download*:
```java
ContentDisposition disposition = ContentDisposition
.attachment()
.filename(resource.getFilename())
.build();
```

**Use `InputStreamResource` carefully**:

Specify `Content-Length` using the [`HttpHeaders#setContentLength`](

[To see links please register here]

) method if:

1. The length is known
2. You use `InputStreamResource`

_Reason: Spring won't write `Content-Length` for `InputStreamResource` because Spring can't determine the length of the resource. Here is a snippet of code from `ResourceHttpMessageConverter`_:

```java
@Override
protected Long getContentLength(Resource resource, @Nullable MediaType contentType) throws IOException {
// Don't try to determine contentLength on InputStreamResource - cannot be read afterwards...
// Note: custom InputStreamResource subclasses could provide a pre-calculated content length!
if (InputStreamResource.class == resource.getClass()) {
return null;
}
long contentLength = resource.contentLength();
return (contentLength < 0 ? null : contentLength);
}
```

In other cases Spring sets the `Content-Length`:

```bash
~ $ curl -I localhost:8080/downloadPdf.pdf | grep "Content-Length"
Content-Length: 7554270
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through