I have below client code:
String filePath = "/testzip/123/TEST-test.zip";
target = mainTarget.path("file").path("{filePath}");
Invocation.Builder invocationBuilder = target
.resolveTemplate("filePath", filePath)
.request(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_OCTET_STREAM);
Response response = invocationBuilder.get();
Below is my server code:
#GET
#Path("{filePath}")
#Produces({MediaType.APPLICATION_OCTET_STREAM})
public Response get(#PathParam("filePath") String filePath) {
File file = new File(filePath);
return Response.status(Response.Status.OK).entity(file).build();
}
This client is throwing Bad Request exception while I send below filePath:
String filePath = "/testzip/123/TEST-test.zip";
But it is working fine when I send below filePath (simple string):
String filePath = "testzip";
I am not able to figure it out why it is not working when forward slash(/) is present in path parameters.
I believe you cannot have / in a #PathParam by default.
EDIT Have a look here : Tomcat, JAX-RS, Jersey, #PathParam: how to pass dots and slashes?
Related
I'm having an issue where I am trying to download a simple "text/plain" file in a spring controller method. I'm getting the text that I exactly want in the web tools response when running the app, which is "test". The response headers in the web developer tools are as follows:
Content-disposition: attachment; filename=file.txt
Content-type: text/plain
Content-length: 4
Length is 4 since that's the number of bytes that the text "test" is. In the controller, I have produces = MediaType.TEXT_PLAIN_VALUE. When I click the associated button in the application to download the file, however, rather than showing the download in the web browser, the download is made to the disk because the file.txt actually shows up in my project's workspace in intellij (which I'm using for my IDE). So, my question is how do I get the download to occur in the web browser, meaning what happens when you click on the 'Download Source Code' button at the following link https://howtodoinjava.com/spring-mvc/spring-mvc-download-file-controller-example/, rather than the file downloading to my workspace/disk?
The support methods/classes look like the following:
public class TextFileExporter implements FileExporter {
#Override
public Path export(String content, String filename) {
Path filepath = Paths.get(filename);
Path exportedFilePath = Files.write(filepath, content.getBytes(),
StandardOpenOption.CREATE);
}
}
public interface FileExporter {
public Path export(String content, String filename);
}
The controller at hand is the following:
#GetMapping(value="downloadFile")
public void downloadFile(HttpServletRequest request, HttpServletResponse response) {
String filename = "example.txt";
String content = "test";
Path exportedpath = fileExporter.export(content, filename);
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
Files.copy(exportedpath, response.getOutputStream());
response.getOutputStream.flush();
}
Try using directly the Response entity to return an InputStreamResource
#RequestMapping("/downloadFile")
public ResponseEntity<InputStreamResource> downloadFile() throws FileNotFoundException {
String filename = "example.txt";
String content = "test";
Path exportedpath = fileExporter.export(content, filename);
// Download file with InputStreamResource
File exportedFile = exportedPath.toFile();
FileInputStream fileInputStream = new FileInputStream(exportedFile);
InputStreamResource inputStreamResource = new InputStreamResource(fileInputStream);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
.contentType(MediaType.TEXT_PLAIN)
.contentLength(exportedFile.length())
.body(inputStreamResource);
}
As #chrylis -cautiouslyoptimistic said try avoiding using low level objects, let it handle it by Spring itself
Below is the server side code for sending file to client as rest response using micronaut.
#Get(value = "/downloadFile", produces = MediaType.APPLICATION_OCTET_STREAM )
public HttpResponse<File> downloadDocument() throws IOException {
File sampleDocumentFile = new File(getClass().getClassLoader().getResource("SampleDocument.pdf").getFile());
return HttpResponse.ok(sampleDocumentFile).header("Content-Disposition", "attachment; filename=\"" + sampleDocumentFile.getName() + "\"" );
}
Below is the client for calling the above endpoint.
#Client(value = "/client")
public interface DownloadDocumentClient {
#Get(value = "/downloadDocument", processes = MediaType.APPLICATION_OCTET_STREAM)
public Flowable<File> downloadDocument();
}
Tried to retreive file as below :-
Flowable<File> fileFlowable = downloadDocumentClient.downloadDocument();
Maybe<File> fileMaybe = fileFlowable.firstElement();
return fileMaybe.blockingGet();
Getting exception as
io.micronaut.context.exceptions.ConfigurationException: Cannot create
the generated HTTP client's required return type, since no
TypeConverter from ByteBuffer to class java.io.File is registered
You cannot send file data using File instance because it contains only path and not file content. You can send file content using byte array.
Update the controller in this way:
#Get(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM)
public HttpResponse<byte[]> downloadDocument() throws IOException, URISyntaxException {
String documentName = "SampleDocument.pdf";
byte[] content = Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource(documentName).toURI()));
return HttpResponse.ok(content).header("Content-Disposition", "attachment; filename=\"" + documentName + "\"");
}
Client will be then like this:
#Get(value = "/download", processes = MediaType.APPLICATION_OCTET_STREAM)
Flowable<byte[]> downloadDocument();
And finally client call:
Flowable<byte[]> fileFlowable = downloadDocumentClient.downloadDocument();
Maybe<byte[]> fileMaybe = fileFlowable.firstElement();
byte[] content = fileMaybe.blockingGet();
Update:
If you need to save received bytes (file content) into the file on a client machine (container) then you can do that for example like this:
Path targetPath = Files.write(Paths.get("target.pdf"), fileMaybe.blockingGet());
And if you really need instance of File instead of Path for further processing then simply:
File file = targetPath.toFile();
I would like to upload file to my web server.
My server implement RESTful API.
To upload file i should pass 4 parameters: file, file_name, project, version
I would like to upload file with this 3 parameters from console. I tried this
URL obj = new URL(MY_URL);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(con.getOutputStream());
ToSend send = new ToSend();
send.file = Files.readAllBytes(Paths.get("path"));
send.file_name = "name";
send.project = "test";
send.version = "1";
objectOutputStream.writeObject(send);
objectOutputStream.flush();
objectOutputStream.close();
and the object i send look like this
class ToSend implements Serializable {
byte[] file;
String file_name;
String project;
String version;
}
I get Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL:
If this is important my server written in Java+Spring and method for this has next signature
#RequestMapping(value = "/", method = RequestMethod.POST)
public #ResponseBody
Response<Boolean> upload(
#RequestParam("project") String project,
#RequestParam("version") String version,
#RequestParam("file_name") String fileName,
#RequestParam("file") MultipartFile file
) throws ServiceException, BadFileExtension {
boolean success = storageService.uploadFile(file, project, fileName, version);
return builder.get(success);
}
This solutions works for me. Maybe useful for someone too.
http://www.codejava.net/java-se/networking/upload-files-by-sending-multipart-request-programmatically
I have a web service developed using Eclipse. Now I want to test it using RESTClient program. I want the client to download the video, which I have defined like this in Eclipse:
#Path("/university")
public class Video {
//this is the location of the .avi
private static final String VIDEO_FILE = "F:\\file.avi";
#GET
#Path("/video")
#Produces("video/avi")
public Response getVideoFile() {
File file = new File(VIDEO_FILE);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=\"abc.avi\"");
return response.build();
}
#GET
#Path("/{fileName}/video")
#Produces("video/avi")
public Response getFileInVideoFormat(#PathParam("fileName") String fileName) {
System.out.println("File requested is : " + fileName);
if (fileName == null || fileName.isEmpty()) {
ResponseBuilder response = Response.status(Status.BAD_REQUEST);
return response.build();
}
File file = new File("c:/abc.avi");
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=abc.avi");
return response.build();
}
}
but I am getting errors when I test using RESTClient (where I specify METHOD=GET, HEADER(key=accept,value=video/avi)). What might the problem?
First, if your REST service does not #Consume something, you don't have to specify "Accept" parameter in header (see HTTP request specification).
Second, your call should look like contextpath/university/video or contextpath/university/filename/video.
Third, don't use ambiguous REST paths like /video and /{anystring}/video, your application server can understand your calls wrong. Use patterns (for example /{id:[0-9]+) or rename /{filename}/video to /video/{filename} to avoid ambiguousness.
I am writing a client for one of my REST API using jersey(org.glassfish.jersey.client.*).
api url is : http://localhost:5676/searchws/search/getresults (POST)
this api returns a json response. i need to provide a payload using jersey client and thats where i am stuck. FOllowing is a sample extract of payload which i need to provide (preferably as string)
Question is how can i provide a payload (XML/JSON) as string or entity to my webtarget.
I saw the answer to providing payload mentioned by calden How to send Request payload to REST API in java? but i am looking for a way to do it in jersey client.
Here is my code till now which does not work fully for post requests.
public class RequestGenerator
{
private WebTarget target;
private ClientConfig config;
private Client client;
private Response response;
public RequestGenerator(Method RequestSendingMethod) throws Exception
{
switch (RequestSendingMethod)
{
case POST :
config = new ClientConfig();
client = ClientBuilder.newClient(config);
target = client.target("http://localhost:5676/searchws").path("search").path("getresults");
String payload = "{\"query\":\"(filter:(\\\"google\\\")) AND (count_options_availbale:[1 TO *])\"}"; //This is just a sample json payload actual one is pretty large
response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json("")); // What to do here
String jsonLine = response.readEntity(String.class);
System.out.println(jsonLine);
}
}
You specify payload as the argument to Entity.json
String payload = "{\"query\":\"(filter:(\\\"google\\\")) AND (count_options_availbale:[1 TO *])\"}";
response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(payload));
I got this working using following code, Salil's code works fine as well(+1 with thanks to him), thanks everyone who contributed to this problem, loving stackoverflow:
public class RequestGenerator
{
private WebTarget target;
private ClientConfig config;
private Client client;
private Response response;
public RequestGenerator(Method RequestSendingMethod) throws Exception
{
switch (RequestSendingMethod)
{
case POST :
String payload = "\r\n{\r\n\"query\": \"google \",\r\n\"rows\": 50,\r\n\"return_docs\": true,\r\n\"is_facet\": true\r\n}"; //this is escapped json string in single line
config = new ClientConfig();
client = ClientBuilder.newClient(config);
target = client.target("http://localhost:7400/searchws/search/getresults");
response = target.request().accept(MediaType.APPLICATION_JSON).post(Entity.entity(payload, MediaType.APPLICATION_JSON), Response.class);
processresponse(response); //This could be any method which processes your json response and gets you your desired data.
System.out.println(response.readEntity(String.class));
break;
case GET :
config = new ClientConfig();
client = ClientBuilder.newClient(config);
target = client.target("http://localhost:7400/search-service/searchservice").path("search").path("results").path("tiger");
response = target.request().accept(MediaType.APPLICATION_JSON).get();
processresponse(response); //This could be any method which processes your json response and gets you your desired data.
System.out.println(response.readEntity(String.class));
}
}