WebClient - Flux<DataBuffer> - Content not getting created - spring-webclient

I am trying to download a file form remote location using Spring WebClient and when I does that , the file is getting created but the content is not getting created. The File still remain 0KB. Any help ,
Flux<DataBuffer> dataBuffer = emailTemplateWebclient
.get()
.uri(gitHubEmailTemplateURL + fileName + ".html")
.retrieve()
.bodyToFlux(DataBuffer.class);
dataBuffer.subscribe();
DataBufferUtils
.write(dataBuffer, destination, StandardOpenOption.CREATE).block();

Related

Read file from Springboot Resources in Docker Container

I am trying to send email with inline image in the email body. The code is working fine when I am running it locally from eclipse. But when it's getting dockerized and deployed to Kubernetes cluster it's unable to read the png file.
I am getting the error "java.io.FileNotFoundException: class path resource [External_Files/email_template.png] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/External_Files/email_template.png"
Project structure screen shot
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
message.setSubject(AppConstants.EMAIL_SUBJECT);
MimeMultipart multipart = new MimeMultipart(AppConstants.RELATED);
MimeBodyPart messageBodyPart = new MimeBodyPart();
String html = AppConstants.EMAIL_HTML_PART_1 + recepientName +
AppConstants.EMAIL_HTML_PART_2
+ fromName + AppConstants.EMAIL_HTML_PART_3 + appProperties.getEmailOnboardPage()
+ AppConstants.EMAIL_HTML_PART_4 + appProperties.getEmailHelpPage()
+ AppConstants.EMAIL_HTML_PART_5;
messageBodyPart.setContent(html, AppConstants.TEXT_HTML);
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyPart2 = new MimeBodyPart();
DataSource fds = new FileDataSource(ResourceUtils.getFile(src/main/resources/External_Files/email_template.png));
messageBodyPart2.setDataHandler(new DataHandler(fds));
messageBodyPart2.setHeader(AppConstants.CONTENT_ID, AppConstants.IMAGE_HEADER);
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
message.setHeader(AppConstants.X_PRIORITY, AppConstants.ONE);
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
log.info("executing Transport.send");
Transport.send(message);
png
#Indranil Halder I know it's late to answer but for others who have this problem finding this issue would be useful
you can use ResourceLoader to find classpath in spring jar file
#Autowired
ResourceLoader resourceLoader;
Resource resource = resourceLoader.getResource("classpath:External_Files/email_template.png");

Spring boot embedded tomcat - 413 Request Entity Too Large

I'm running on the IBM public cloud. I have apu connect to access the cloud foundry microservice. I've gone through many of the posts and tried various things and I can't seem to get this to work. Here are my property file config settings for spring boot:
# The name of the application
spring.application.name=xxxxx
# web base path
management.endpoints.web.base-path=/
# Embedded tomcat config
server.tomcat.max-swallow-size=256MB
server.tomcat.max-http-post-size=256MB
# File size values
spring.servlet.multipart.max-file-size=256MB
spring.servlet.multipart.max-request-size=256MB
spring.servlet.multipart.enabled=true
# Server specific values
input.server=xxx
input.rtm.bucket=xxx
storage.server.base=xxx
# Cloudant database info
input.events.db.name=xxxx
input.ait.info.db.name=xxxx
letter.number.db.name=xxxx
letter.gen.data.db.name=xxxx
# Query index design documents
query.pad.ait.info.index.name=xxxx
query.pad.ait.info.deisgn.doc=_xxxx
query.rfa.ltr.index.name=xxxx
query.rfa.ltr.design.doc=xxxx
# The logging levels of the application
logging.level.application=DEBUG
#logging.level.root=DEBUG
#logging.level.org.springframework.web=INFO
# Testing
unit.testing=false
integration.testing=true
# Jackson json config
spring.jackson.mapper.accept-case-insensitive-properties=true
Here is the REST api function for POSTing the file
#PostMapping(value = "/send/rtm/document/{errata}")
public #ResponseBody ResponseEntity<Object> receiveRtmDocument(#PathVariable("errata") String errata, #RequestParam("file") MultipartFile file)
I'm using spring boot 2.1.6 and have not updated anything in the POM file. I'm attempting to send a 5.8 MB file to the api and it gives me this error:
com.ibm.tools.cloud.exceptions.DataNotJsonException: <html>
<head><title>413 Request Entity Too Large</title></head>
<body bgcolor="white">
<center><h1>413 Request Entity Too Large</h1></center>
<hr><center>openresty</center>
</body>
</html>
at com.ibm.msc.gasm.sapt.input.AitInputManagement.sendRtmDocument(AitInputManagement.java:182)
at com.ibm.msc.gasm.sapt.test.InputServiceTester.performTest(InputServiceTester.java:142)
at com.ibm.msc.gasm.sapt.test.InputServiceTester.main(InputServiceTester.java:96)
Here is the send code I am using in java for the multipart. The only other headers I use that are not listed here are my authorization headers.
// Create the URL connection
HttpURLConnection conn = (HttpURLConnection) (new URL(requestUri)).openConnection();
if (content != null || multipartFile) conn.setDoOutput(true);
conn.setRequestMethod(method.toString());
// Set the headers
Enumeration<String> keys = headers.keys();
while (keys.hasMoreElements())
{
// Pull out the key
String key = keys.nextElement();
// Set the header
conn.setRequestProperty(key, headers.get(key));
}
// Set the accept header
if (acceptHeader != null) conn.setRequestProperty("Accept", acceptHeader);
// Set the content header
if (contentTypeHeader != null) conn.setRequestProperty("Content-Type", contentTypeHeader);
if (content != null)
{
// Set the content
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
if (content.isFileContent()) dos.write(content.getFileContentAsByteArray());
else if (content.isByteArrayContent()) dos.write(content.getContentAsByteArray());
else if (content.isStringContent()) dos.write(content.getStringContentAsByteArray());
// close the stream
dos.flush();
dos.close();
}
// Set the multipart file
if (multipartFile)
{
// Set the properties
conn.setUseCaches(false);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundry=" + MP_BOUNDRY);
// Set the content
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(MP_HYPHENS + MP_BOUNDRY + StringUtils.crlf);
dos.writeBytes("Content-Disposition: form-data: name=\"" + this.mpName + "\";filename=\"" + this.mpFileName + "\"" + StringUtils.crlf);
dos.writeBytes(StringUtils.crlf);
dos.write(IOUtils.toByteArray(new FileInputStream(this.mpFileNamePath)));
dos.writeBytes(StringUtils.crlf);
dos.writeBytes(MP_HYPHENS + MP_BOUNDRY + MP_HYPHENS + StringUtils.crlf);
// close the stream
dos.flush();
dos.close();
}
// Get the response
HttpResponseMessage response = null;
try
{
// Extract the stream
InputStream is = (conn.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) ? conn.getErrorStream() : conn.getInputStream();
// Pull out the information
byte[] data = IOUtils.toByteArray(is);
// Set the response
response = new HttpResponseMessage(requestUri, HttpStatusCode.getType(conn.getResponseCode()), acceptHeader, data, conn.getResponseMessage());
}
catch (Throwable e)
{
throw new IOException(String.format("Error reading results from %s", requestUri), e);
}
// Close the request
conn.disconnect();
// Send request
return response;
I've tried several things, but I am not sure what I am missing. Anyone have any ideas how to fix this?
You need to change NGINX settings;
Add to config file next line
client_max_body_size 20M;
Use the form form to submit the file and accept it with MultipartFile. In this case (the other situation is not clear), the default file size is limited to 2M. If you want to upload a large file, you need to configure the file size.
https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/
Try these two in your application.properties
server.tomcat.max-swallow-size=XMB //maximum size of the request body/payload
server.tomcat.max-http-post-size=XMB //maximum size of entire POST request
X is your desired integer representing megabyte.

Spring REST file download unable to set header content-type attachment

I have a Springboot REST application that downloads files from a given directory.
The downloads can be any file file and have any format, and I want to use the original filename as the filename of the downloaded file.
I used the code below to set the filename in the header, and add the header to the response:
#RestController
#RequestMapping("/downloads")
public class DownloadCsontroller {
...
#GetMapping
public void downloadSingleFile(#RequestParam("file") String filename, HttpServletResponse response) throws IOException {
String filepath = m_attachmentPathLocation + File.separator + filename;
File file = new File(filepath);
String contentType = getContentType(file);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType(contentType);
response.setHeader("Content-Disposition:", "attachment;filename=\"" + file.getName() + "\"");
...
}
...
}
Tested using both "Content-Disposition" and "Content-Disposition:" in setHeader().
Almost everything works (file types), except for PDF, ZIP, RAR, EXE, etc.
Any files (types) not on the list can be downloaded with the desired filenames.
But when any of the file download (PDF, ZIP, RAR, EXE, etc)... it seems it continuously loads like forever... and I cannot even see any request sent in POSTMAN, inspector, firebug, etc.
If I comment out:
//response.setHeader("Content-Disposition:", "attachment;filename=\"" + file.getName() + "\"");
It would work, but the filename would be set to the name of the request mapping. which in this case is "downloads".
I have seen lots of samples that uses "Content-Disposition" header to change the attachment filename... but it seems it fails on these file types.
I have no configurations yet, and it is kinda weird since in most samples I searched... this should be running or working.
TIA
Please add #GetMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
and instead of returning direct file try to return stream.
Also make a note that "Content-Disposition:" header will not work if the requesting app IP & Port number is different from server app IP & Port number.
Things would work If you can alter the code a bit, by setting all header values using org.springframework.http.HttpHeaders class.
Now looking at your code, i suspect you trying to expose an API that allows to download a multipart File.
I would suggest you not to use HttpServletResponse Class to set the Content- Dispositionheader but use HttpHeaders class. Below is the reformatted code
#RestController
public class DownloadCsontroller {
#GetMapping(value="/downloads")
public ResponseEntity<Object> downloadSingleFile(#RequestParam("file")
String filename) throws IOException {
String filepath = m_attachmentPathLocation + File.separator + filename;
File file = new File(filepath);
String contentType = getContentType(file);
/* response.setStatus(HttpServletResponse.SC_OK);
response.setContentType(contentType);
response.setHeader("Content-Disposition:", "attachment;filename=\""
+ file.getName() + "\"");
*/
// Here is the below Code you need to reform for Content-
//Disposition and the remaining header values too.
HttpHeaders headers= new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename
=whatever.pdf");
headers.add("Content-Type",contentType);
// you shall add the body too in the ResponseEntity Return object
return new ResponseEntity<Object>(headers, HttpStatus.OK);
}
}

I need the Jersey Multipart Client and server code to Upload more than one file.?

I need the Jersey Multipart Client to Upload more than one file.
I am able to upload a Single file but how can i upload more than one file.
In the client i set the two filedatabody parts.
final FileDataBodyPart filePart = new FileDataBodyPart("file", new File("path"));
FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
FileDataBodyPart filePart2 = new FileDataBodyPart("file", new File("path2"));
final FormDataMultiPart multipart =
(FormDataMultiPart) formDataMultiPart.field("foo", "bar").bodyPart(filePart).bodyPart(filePart2);
How to write the server side code.
The "file" you're using here new FileDataBodyPart("file", new File("path2")); is the name of the body part. If you are going to name them the same (which is allowed), then use a List for your parameter type
public Response upload(#FormDataParam("file") List<InputSream> files)
Otherwise if you want to change the name of one of the parts, then just add another #FormDataParam parameter using that part's name
public Response upload(#FormDataParam("file1") InputStream file1,
#FormDataParam("file2") InputStream file2)

Spring Boot and ConfigServer

We have a SpringBoot application which is successfully comunicating with config server.
The question I have is... say we have a application properties file and a csv file in config server.
when application starts if we want to get the contents of csv file too whats the better approach.
We are able to get it by doing a direct http connection to configserver and retreive the csv file contents
String url = configServerURL+"/*/*/*/example.csv";
byte[] encoded = Base64.encode((uname + ":" + password).getBytes());
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("Authorization", "Basic "+encoded);
int responseCode = con.getResponseCode();
wanted to check what options are there.

Resources