How to send file in JAVA via POST without saving it to disk - spring

I need to send file to a POST service from the server side code.
The content of the file I need to send is in String format.
I don't want to create the file in the disk.
I can't find the way to send file without creating it in the disk.
I prefer not to create a TEMP file but this is what I managed to do.
How do I send file without saving it to disk, not even as TEMP file?
This is the code:
String fileContent = generateFile();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("apikey","myapikey");
File tmpFile = File.createTempFile("test", ".tmp");
FileWriter writer = new FileWriter(tmpFile);
writer.write(fileContent);
writer.close();
BufferedReader reader = new BufferedReader(new FileReader(tmpFile));
reader.close();
FileSystemResource fsr = new FileSystemResource(tmpFile);
MultiValueMap<String, Object> body
= new LinkedMultiValueMap<>();
body.add("file",fsr);
HttpEntity<MultiValueMap<String, Object>> requestEntity
= new HttpEntity<>(body, headers);
String serverUrl = "https://api.com/api";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity(serverUrl, requestEntity, String.class);
return response.getBody();
POSTMAN screenshot that I use to test the API and it works perfect

Use a ByteArrayResource instead:
String fileContent = generateFile();
ByteArrayResource bar = new ByteArrayResource(fileContent.getBytes());
This way you will not have to create any resource on disk but keep it in memory instead.

Related

Create mock server to test on result of RestTemplate

I am not sure if it is possible to write a Test case that can mock the "http://localhost:8888/setup" site, so the above code can hit it and I want to check if the "http://localhost:8888/setup" received the inputStream correctly.
InputStream inputStream = //got the inputStream;
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
InputStreamResource inputStreamResource = new InputStreamResource(inputStream){
#Override
public String getFilename(){
return filename;
}
#Override
public long contentLength(){
return -1;
}
}
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>():
body.add("file", inputStreamResource);
HttpHeader headers = new HttpHeader();
headers.setContentType(MediaType.MULTIPART_FORM_DATA)LinkedMultiValueMap
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
String url = "http://localhost:8888/setup";
restTemplate.postForObject(url, requestEntity, String.class);
Try using Wiremock!
Many ways of using it, back then when I used it, I used to run a JAR (wiremock jar) and it spawns up a program on your localhost with your port specified. Henceforth, you can test by hitting that localhost on the port it's up!
For reference check this out :
https://www.softwaretestinghelp.com/wiremock-tutorial/
https://www.baeldung.com/introduction-to-wiremock
https://github.com/wiremock/wiremock

Upload to google drive using The files get uploaded, but, only in the root and are always named "Untitled"

I am trying to upload files to Google drive using a REST API
Everything is working fine, but files are uploading into Google Drive only in the root, and with "Untitled" as their name.
public class UploadTODrive {
public static DriveFiles UploadFileTODrive(String accessToken, MultipartFile files) throws IOException {
RestTemplate restTemplate = new RestTemplate();
String requestUri = "https://www.googleapis.com/upload/drive/v2/files";
System.out.println("ContentType==============: " + files.getContentType());
byte[] s=files.getBytes();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", files.getContentType());
headers.setContentLength(0);
//headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.add("Authorization", "Bearer " + accessToken);
HttpEntity<byte[]> requestEntity = new HttpEntity<>(s, headers);
ResponseEntity<String> response = restTemplate.exchange(requestUri, HttpMethod.POST, requestEntity,
String.class);
System.out.println("=====>Response: " + response);
Gson gson = new Gson();
DriveFiles driveFiles = gson.fromJson(response.getBody(), DriveFiles.class);
return driveFiles;
}
}
Files are uploaded to google drive in two parts.
The first part is the meta data of the file, this being the name and the mimetype most often and occasionally containing a parent directory.
The second part is the upload of the actual file stream.
It seams that you are uploading the file stream but you have forgotten to post the file metadata. This is posted in the body of your request
This is your HTTP Post request. You need to figure out how to add a post body to this. This is the documentation link to the writable fields that you can post insert#request-body
ResponseEntity<String> response = restTemplate.exchange(requestUri, HttpMethod.POST, requestEntity,
String.class);
Update
found this with a bit of googling
RESTRequest1.AddBody('{"title": "Capture.jpg"}', TRESTContentType.ctAPPLICATION_JSON);

Sending a multipart request using RestTemplate

I want to make a multipart request to some external API (created using Spring Boot) but all I get is Required request part 'file' is not present.
I know the source code of the external API but I can't modify it. It looks like this:
#PostMapping("/upload")
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile file){
return ResponseEntity.ok().build();
}
And from my application I create and send requests exactly like on the following snippet:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body
= new LinkedMultiValueMap<>();
body.add("file", "dupa".getBytes());
HttpEntity<MultiValueMap<String, Object>> requestEntity
= new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity("http://api:8080/upload", requestEntity, String.class);
return response.getBody();
What's the reason it doesn't work? The above code rewritten using Apache HttpClient works like charm.
You basically have two options, the solution with byte array:
map.add("file", new ByteArrayResource(byteArrayContent) {
#Override
public String getFilename() {
return "yourFilename";
}
});
I remember having a problem with just adding a byte array, so you need to have a filename too and use ByteArrayResource.
Or adding a File:
map.add("file", new FileSystemResource(file));

uploading multipart file to another server

I'm working on a spring boot / Angular 6 application, I want to upload files to a server, I followed this tutorial to upload a multipart file :" https://grokonez.com/spring-framework/spring-boot/angular-5-upload-get-multipartfile-to-from-spring-boot-server ". The upload of the file is on a folder in the application but now I want to upload the files to another server with URL; f.e : localhost:8081/uploads : it's another server, how can I do that?
You should do this with spring rest template and construct the body as below
MultiValueMap<String, Object> body
= new LinkedMultiValueMap<>();
body.add("files", getTestFile());
body.add("files", getTestFile());
body.add("files", getTestFile());
HttpEntity<MultiValueMap<String, Object>> requestEntity
= new HttpEntity<>(body, headers);
String serverUrl = "http://localhost:8081/upload/";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate
.postForEntity(serverUrl, requestEntity, String.class);

Post data using Spring RestTemplate

I am trying to post data using Spring RestTemplate as below:
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.add("name1", "value1");
parameters.add("name2", "value2");
HttpMessageConverter<String> stringConverter = new StringHttpMessageConverter();
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
List<HttpMessageConverter<?>> msgConverters = new ArrayList<HttpMessageConverter<?>>();
msgConverters.add(formConverter);
msgConverters.add(stringConverter);
restTemplate.setMessageConverters(msgConverters);
String xml = restTemplate.postForObject(myurl, parameters, String.class);
On the server part, I am using a simple servlet to handle request as follow:
String name1 = request.getParameter("name1");
The server returns the xml as String.
When I used HashMap instead of MultiValueMap without Converter, the parameters are null on the server side. But after using the above code, I am getting error
Cannot extract response: no Content-Type found
Can you plz provide me a simple example to achieve what I want.
Here is what I used to format data for the Spring POST:
//FormHttpMessageConverter
is used to construct form parameters to POST on the URI
HttpMessageConverter<?> formHttpMessageConverter = new FormHttpMessageConverter();
HttpMessageConverter<?> stringHttpMessageConverter = new StringHttpMessageConverter();
List<HttpMessageConverter> msgConverters = new ArrayList<HttpMessageConverter>();
msgConverters.add(formHttpMessageConverter);
msgConverters.add(stringHttpMessageConverter);
// Prepare acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.ALL);
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<MultiValueMap<String,String>> httpEntity = new HttpEntity<MultiValueMap<String,String>>(map,headers);
ResponseEntity<String> resp = restTemplate.exchange("https://risk.XXXX.XXXXXX.net",HttpMethod.POST,httpEntity,String.class);

Resources