I am having trouble passing multiple parameters to GET resource in my controller. I have created a named query in my repository. When i call this GET endpoint, it should execute the named query by passing parameters.
Below code should take multiple parameters as input for example ID = 1,2,3,4 etc. It only takes single input as param.
#GetMapping("/message/{Ids}")
#CrossOrigin(origins = "*")
public void multidownload(#PathVariable Long[] Ids , HttpServletResponse response)throws Exception {
List<MessageRepository> messageRepository = Repository.findbyId(Ids);
String xml = new ObjectMapper().writeValueAsString(messageRepository);
String fileName = "message.zip";
String xml_name = "message.xml";
byte[] data = xml.getBytes();
byte[] bytes;
try (ByteOutputStream bout = new ByteOutputStream();
ZipOutputStream zout = new ZipOutputStream(bout)) {
zout.setLevel(1);
ZipEntry ze = new ZipEntry(xml_name);
ze.setSize(data.length);
zout.putNextEntry(ze);
zout.write(data);
zout.closeEntry();
bytes = bout.getBytes();
}
response.setContentType("application/zip");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition", "attachment; " + String.format("filename=" + fileName));
ServletOutputStream outputStream = response.getOutputStream();
FileCopyUtils.copy(bytes, outputStream);
outputStream.close();
}
downloaded zip file should contain multiple ID records which were passed as parameter when calling the GET endpoint.
can someone look into my code and point out what needs changing?
You can rewrite it to List of Ids - `List Ids
#GetMapping("/message/{Ids}")
#CrossOrigin(origins = "*")
public void multidownload(#PathVariable List<Long> Ids , HttpServletResponse response)throws Exception {
...
You achieve the multiple input parameters in POST request method.
In the request payload, please add this array of integer in your Request payload.
[1,2,3,4,5]
To achieve same thing in GET request method convert your array of integer into string.
Example:
localhost:8080/user/str=1,2,3
Related
Using intellij, Java and restassured:
I am sending the request as needed and I added this to my code:
public static Response PostInstinctQuery() throws IOException, ParseException {
PrintStream fileOutPutStream = new PrintStream(new File("request_log.txt"));
config = config().logConfig(new LogConfig().defaultStream(fileOutPutStream));
RestAssured.baseURI = BASEURI;
RequestSpecification request = RestAssured.given();
//Headers
request.header("Key",key);
request.body(getJson());
request.log().all();
Response response = request.post(PATH);
return response;
}
That is save the request in "request_log.txt" file.
so what is the problem ? the file shows the same request over and over.
If I use TestNG diff data then I would expect that the file will contain all the diff request.
And I really want the request to be able to save in a String variable for assert / report purposes also.
Thanks!
I think you can use RequestLoggingFilter to config one time, no need log().all().
OutputStream file = new FileOutputStream("request_log.txt");
PrintStream stream = new PrintStream(file, true);
RestAssured.filters(RequestLoggingFilter.logRequestTo(stream));
I have a rest api which allows me to pass multiple IDS to a resource to download records from specific table and zip it. MSSQL is the backend mastering messages.
So when a ID is passed as param, it calls the database table to return the message data. Below is the code:
#GetMapping("message/{ids}")
public void downloadmessage(#PathVariable Long[] ids, HttpServletResponse response) throws Exception {
List<MultiplemessageID> multiplemessageID = auditRepository.findbyId(ids);
String xml = new ObjectMapper().writeValueAsString(MultiplemessageID);
String fileName = "message.zip";
String xml_name = "message.xml";
byte[] data = xml.getBytes();
byte[] bytes;
try (ByteOutputStream bout = new ByteOutputStream(); ZipOutputStream zout = new ZipOutputStream(bout)) {
for (Long id : ids) {
zout.setLevel(1);
ZipEntry ze = new ZipEntry(xml_name);
ze.setSize(data.length);
ze.setTime(System.currentTimeMillis());
zout.putNextEntry(ze);
zout.write(data);
zout.closeEntry();
}
bytes = bout.getBytes();
}
response.setContentType("application/zip");
response.setContentLength(bytes.length);
response.setHeader("Content-Disposition", "attachment; " + String.format("filename=" + fileName));
ServletOutputStream outputStream = response.getOutputStream();
FileCopyUtils.copy(bytes, outputStream);
outputStream.close();
}
Message on the database has the following structure:
MSG_ID C_ID NAME INSERT_TIMESTAMP MSG CONF F_NAME POS ID INB HEADERS
0011d540 EDW,WSO2,AS400 invoicetoedw 2019-08-29 23:59:13 <invoice>100923084207</invoice> [iden1:SMTP, iden2:SAP, service:invoicetoedw, clients:EDW,WSO2,AS400, file.path:/c:/nfs/store/invoicetoedw/output, rqst.message.format:XML,] p3_pfi_1 Pre 101 MES_P3_IN [clients:EDW,WSO2,AS400, UniqueName:Domain]
My file name should be like: part of header name + _input parameterId[0]
i.e. Domain_1
File name for multiple paramter (1,2,3,4)will be like
Domain_1
Domain_2
Domain_3
Domain_4
Below code retrieves the part of file name as string from the header.
private static String serviceNameHeadersToMap(String headers) {
String sHeaders = headers.replace("[", "");
sHeaders = sHeaders.replace("]", "");
String res = Arrays.stream(sHeaders.split(", "))
.filter(s->s.contains("serviceNameIdentifier"))
.findFirst()
.map(name->name.split(":")[1])
.orElse("Not Present");
return res;
I need to create a file name with header and input parameter. Once the file name is set, I would like individual records downloaded with correct file name and zipped.
Zip file name is message.zip. When unzipped it should contain individual files like Domain_1.xml, Domain_2.xml, Domain_3.xml, Domain_4.xml etc...
How do I achieve this? Please advise. I need some guidance for the limited knowledge on java I have. Thank you.
I'm wondering if there a real difference when a Sprin MVC controller method returns byte array byte[] to represent a downloaded file or when I copy InputStream object to the ServletOutputStream object?
The reason I'm asking is that I have to make sure that there won't be any OutOfMemory errors when downloading large files. Will the passing file through the ServletOutputStream help to avoid it?
Passing byte array:
byte[] download() {
return getUrlContentAsByteArray();
}
Passing in the ServletOutputStream:
void download(HttpServletResponse response) {
InputStream content = getUrlContentAsStream();
ServletOutputStream outputStream = response.getOutputStream();
response.reset();response.setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
IOUtils.copyLarge(inputStream, outputStream);
}
In your first example, you have to read the entire response into memory and store it in a byte array. That will require at least as much memory as the size of the response.
In your second example, you do not keep the entire response in memory at once, but use IOUtils.copy to copy the content in multiple, small chunks from the source and into the servlet response. IOUtils is by default using a 4kB large buffer. You are however using a strange mix of both Spring and Servlet APIs.
Using Spring MVC alone, you can leave out the servlet API, return the InputStream wrapped as a Resource and let Spring do the copy job for you:
#RequestMapping(value = "/download", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Resource> download() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
InputStream is = null; // get your input stream here
Resource resource = new InputStreamResource(is);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
How to write java code for egnyte chunked upload and send to rest service of egnyte api.
https://developers.egnyte.com/docs/read/File_System_Management_API_Documentation#Chunked-Upload
long size = f.getTotalSpace();
int sizeOfFiles = 1024 * 1024;// 1MB
byte[] buffer = new byte[sizeOfFiles];
ResponseEntity<String> responseEntity = null;
String fileName = f.getName();
String url = DOWNLOAD_OR_UPLOAD + "-chunked" + egnyteSourcePath + f.getName();
HttpHeaders headers = buildEgnyteEntity();
HttpEntity entity = new HttpEntity<>(headers);
//try-with-resources to ensure closing stream
try (FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis)) {
int bytesAmount = 0;
while ((bytesAmount = bis.read(buffer)) > 0) {
//write each chunk of data into separate file with different number in name
String filePartName = String.format("%s.%03d", fileName, partCounter++);
File newFile = new File(f.getParent(), filePartName);
responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
}
}
return responseEntity;
I think there's a couple of things missing in your code.
First thing is that you don't specify required headers. You should provide X-Egnyte-Chunk-Num with int value with number of your chunk, starting from 1. In X-Egnyte-Chunk-Sha512-Checksum header you should provide SHA512 checksum.
Second thing is that first request will give you an UploadId in response header in X-Egnyte-Upload-Id. You need to specify that as a header in your second and following requests.
Third thing is that I don't see you use your bytesAmount in the request. I'm not sure you're providing the data.
I'm not a Java guy, more of a C# one, but I've written a post how to upload and download big files with Egnyte API on my blog: http://www.michalbialecki.com/2018/02/11/sending-receiving-big-files-using-egnyte-api-nuget-package/. This can give you an idea how sending loop can be structured.
Hope that helps.
Problem: Contents of a CSV file are getting displayed as page contents if the number of records is large.
Expected: File download.
The request gets fired from another page via window.open(url); Following is the url handler.
#RequestMapping(value = "/url", method = RequestMethod.GET)
public void handler(HttpServletRequest request,ModelMap map, #RequestParam("itemPk") long pk, HttpServletResponse response) throws Exception {
CSVWriter csvWriter = new CSVWriter(new OutputStreamWriter(response.getOutputStream()));
try {
List<String[]> data = new ArrayList<String[]>();
for (int i = 0; i < 500; i++) {
String[] row = new String[] {"asdr", "10", "sourajit", "34.567", "06-DEC-2015", "awx445"};
data.add(row);
}
csvWriter.writeAll(data);
response.setContentType("text/csv");
response.setHeader("Content-disposition", "attachment; filename=volcs.csv");
} finally {
csvWriter.flush();
csvWriter.close();
}
}
Same behavior for GET or POST.
(For POST, opening a new window with a html form)
This is because a Writer instance is used for generating the response.
We need to treat it as bytes.
ServletOutputStream out = response.getOutputStream();
out.write(baos.toByteArray());
baos.writeTo(out);
out.flush();
You need to add headers to tell browser that its attachment in the response. Check the below!
String filename = "volcs.csv";
response.setContentType("application/force-download");
response.setContentLength((int)f.length());
//response.setContentLength(-1);
//response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=" + filename);