I have a simple servlet that can return a video file to the client. What I want to do is to download the file from a URL onto my server and then send that newly downloaded file to the client. My problem is the entrance point of the servlet is inside the doGet() method where the client requests the file. I want to download the file once and use it as a static file. However, because I call the download function inside my doGet(), while the client tries to get the file it keeps repeating everything that happen inside doGet() and my file keeps being overwritten. It really slows down the entire process. Is there anyway I can just call my download function once?
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
answerRequest(request, response);
}
...
public void answerRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException{
String requestedFile = request.getPathInfo();
URL newURL = "fixed URL content";
HttpURLConnection connection = (HttpURLConnection) newURL.openConnection();
sendFile(connection, request, response);
}
...
public void sendFile(HttpURLConnection connection, HttpServletRequest request, HttpServletResponse response){
InputStream input = null;
FileOutputStream output = null;
File videoFile = new File("path-to-file");
input = connection.getInputStream();
output = new FileOutputStream(videoFile);
Utility.download(input, output, 0, connection.getContentLength()); //this is where the file is downloaded onto my server)
connection.disconnect();
close(output);
close(input);
//this is where the file is sent back to client
Utility.sendFile(videoFile, response, request,true);
...
}
So as you can see, all of those function happen every time doGet() happen. But I only want the Utility.download() to execute once. How would I do that?
You can add a boolean flag to Session variable. For example, when the do get is executed for the first Time:
boolean started = true;
Then right before you call Utility.sendFile() check whether the boolean flag is true or false and run the method accordingly.
Related
I have several servlets that do things server side. On a few I just encode some unnecessary data and send it back, which seems pointless. Do you have to respond ? What happens when you just say return ? I've done that before and nothing seems to go wrong but I am relatively new to servlets. Are there consequences for simply returning that go above my head ? And what exactly happens when you return;
if(request.getParameter("name").equals("saveusedcards")) {
String sessId = request.getSession().getId();
//encode request with confirmation that cards were successfully updated
if(usersUpdatedCards.get(sessId).isEmpty()){
//no cards were seen
}
boolean success = DataDAO.updateCards(usersUpdatedCards.get(sessId));
if(success){
System.out.println("Data base update successfull!");
String responseMessage = new Gson().toJson("card successfully udpated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
} else {
System.out.println("Data base update failed...");
String responseMessage = new Gson().toJson("card was not successfully updated");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
System.out.println("updated cards response message: "+responseMessage);
response.getWriter().write(responseMessage);
return;
}
}
The servlet must produce an HTTP response for the client, however it is perfectly acceptable to return no content in the response body. When doing so your servlet should make this clear to the client by sending a response code of 204 (no content). Reference: https://httpstatuses.com/204
Here is an example of how you would set the response code from the doGet method. You could do the same from doPost or service methods.
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// Do whatever work you need to do here...
res.setStatus(HttpServletResponse. SC_NO_CONTENT); // This returns a 204
}
I moved all data in old domain to new one. Many links is indexed by google and its important for us So I want to redirect 301 all link like below:
my_domain.ir/Server?do=content&id=24
to
my_domain.com/Server?do=content&id=24
The code below is Server.java that is a servlet
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("_______________________________________________");
String url = request.getRequestURL().toString() +"?"+ request.getQueryString();
System.out.println(url);// http://my_domain.ir/Server?do=content&id=24
url = url.replace(".ir", ".com");
url = url.replace("localhost:9090", "mydomain.com");//to test from localhost
System.out.println(url);//http://my_domain.com/Server?do=content&id=24
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", url);
response.setHeader( "Connection", "close" );
System.out.println("_______________________________________________");
}
after calling I can see http://my_domain.ir i can see 301 redirect code But in address bar is "http://my_domain.com/Server" and browser dos not open any page.
I try redirect all to http://my_domain.com/index_test.html but the result is same.
Its vary important for us to save my domain position in google, Is this problem harmful?
Just looked it up, because I remembered this (from like 10 years ago), but you can do a redirect much easier:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("_______________________________________________");
String url = request.getRequestURL().toString() +"?"+ request.getQueryString();
System.out.println(url);// http://my_domain.ir/Server?do=content&id=24
url = url.replace(".ir", ".com");
url = url.replace("localhost:9090", "mydomain.com");//to test from localhost
System.out.println(url);//http://my_domain.com/Server?do=content&id=24
response.sendRedirect(url);
System.out.println("_______________________________________________");
}
Disclaimer: I haven't checked whether your URL rewriting is actually correct.
I would like to start a file download from a clickevent in my gwt web app. So I wrote a Servlet which writes the data to the output and should start the download. The data is received via http get.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = request.getParameter("data");
String filename = request.getParameter("filename");
byte[] streamData = data.getBytes();
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment; fileName="
+ filename + ".csv");
response.setContentLength(streamData.length);
ServletOutputStream out = response.getOutputStream();
out.write(streamData);
out.flush();
}
In the client I start the get method via requestBuilder.sendRequest():
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, /download");
requestBuilder.sendRequest("filename=dues&data="+ theDataAsString, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
// Anything to do here?
}
#Override
public void onError(Request request, Throwable exception) {
exception.printStackTrace();
SC.warn("Error while creating export file.");
}
});
Nothing happens. But why? Shouldn't the browser ask to begin a download?
Does it, in this case, matter if i use post or get?
I don't want to use somthing like
Window.open("/download?data=myData&filename=filename", "_blank", "");
Any ideas?
On the client side, use an Anchor instead of a request builder and invoke the servlet directly.
I have a web application with a simple upload function. The idea is to allow user select a file and upon successfully upload, redirect to index.jsp.
However, although the file got uploaded, the response.redirect is not working. After a successfully upload, the page doesn't get redirected. It just stays there. The weird thing is that I can see it is processing the index.jsp from the tomcat server log even though it doesn;t get redirected.
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//processRequest(request, response);
boolean status=false;
if (!ServletFileUpload.isMultipartContent(request)) {
throw new IllegalArgumentException("Request is not multipart, please 'multipart/form-data' enctype for your form.");
}
ServletFileUpload uploadHandler = new ServletFileUpload(new DiskFileItemFactory());
PrintWriter writer = response.getWriter();
response.setContentType("text/plain");
try {
List<FileItem> items = uploadHandler.parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField()) {
File file = new File(getServletContext().getRealPath("/WEB-INF/upload"), item.getName());
item.write(file);
writer.write("{\"name\":\"" + item.getName() + "\",\"type\":\"" + item.getContentType() + "\",\"size\":\"" + item.getSize() + "\"}");
}
}
//redirect to index.jsp if successfully
redirect(request, response);
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
writer.close();
}
}
The redirect method:
private void redirect(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
The file upload plugin is from https://aquantum-demo.appspot.com/file-upload
I used the front-end and developed the upload event handler using java apache fileupload. Everything works fine except the redirect part.
The application.js file which handles the JSON returns:
$(function () {
// Initialize jQuery File Upload (Extended User Interface Version):
$('#file_upload').fileUploadUIX();
// Load existing files:
$.getJSON($('#file_upload').fileUploadUIX('option', 'url'), function (files) {
var options = $('#file_upload').fileUploadUIX('option');
options.adjustMaxNumberOfFiles(-files.length);
$.each(files, function (index, file) {
options.buildDownloadRow(file, options)
.appendTo(options.downloadTable).fadeIn();
});
});
});
Any ideas?
You're attempting to send two responses on a single request. One with JSON data in the response body and one which redirects the response to another request. This is not going to work. You can send only one response back per request. A redirect requires an untouched (uncommitted) response body, otherwise the redirect will just fail with IllegalStateException: response already committed in the server logs.
You need to move the redirect call from the servlet code to JavaScript code. Get rid of the redirect() line in the servlet and add the following line as the last line of the $.getJSON() callback function.
window.location = '/index.jsp';
This way JavaScript will take care of the redirect.
Suddenly stuck on generating custom servlet response. I want to replace servlet response with predefined one:
public class MyCustomResponse extends HttpServletResponseWrapper {
private String customOutput;
public MyCustomResponse(String customOutput, HttpServletResponse response) {
super(response);
// PrintWriter and Outputstream should stream this variable as output
this.customOutput = customOutput;
}
//
// Below I need to override something
//
}
and filter code snipped as follows:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//
//
MyCustomResponse customResponse = new MyCustomResponse("Hello world!", (HttpServletResponse) response);
chain.doFilter(request, customResponse);
}
Shame on me, but i'm really stuck on coding this simple task :(
Any help would be appreciated.
UPDATE:
All I want is to implement custom response wrapper which, once it's put into filter chain, would always respond with some predefined text. I know how to write custom data from within doFilter() method, but I want MyCustomResponse to be responsible for that - just instantiate and put in chain. Any well-reasoned responses "You cant do that because..." are also welcome.
As quoted in one of your comments :
"I want my custom response to return a
string in response to getWriter or
getOutputStream method invocation"
For that, you have to provide your own implementation for getWriter() & getOutputStream() by overriding them.
//---
private PrintWriter printWriter = null;
private ServletOutputStream outputStream = null;
public PrintWriter getWriter( ) throws IOException {
if (this.outputStream != null) {
throw new IllegalStateException(
"Cannot call getWriter( ) after getOutputStream( )");
}
if (this.printWriter == null) {
// initialize printWriter
}
return this.printWriter;
}
public ServletOutputStream getOutputStream( ) throws IOException {
if (this.printWriter != null) {
throw new IllegalStateException(
"Cannot call getOutputStream( ) after getWriter( )");
}
if (this.outputStream == null) {
// initialize outputStream
}
return this.outputStream;
}
//---
I am sorry, but
it is not clear what is your
problem. You code is written, so? It
does not work? what exactly does not work?
Why do you want to do this? The "right" solution is to pass information as session attribute.
I do not believe this can work. Really, you do not call directly the next filter in chain. You are kindly asking the app. server to do this. And you are not expected to replace the servlet request/response by your own. Use method explained above (#2)
Your response wrapper is useless as is, since it only stores a string in the Java object used to model the actual HTTP response.
The actual HTTP response that the client receives is the stream of bytes (resp. characters) sent via the output stream (resp. writer) of the HttpServletResponse object (and the headers, cookies, etc. stored in the HttpServletResponse object).
If you want to send a custom output string to the client, just use response.getWriter().print("Hello worlds!").
Passing the response to the rest of the filter chain is questionable, since the rest of the chain will probably want to add its own data to the response stream.
If you want to hard-code the response to send to the client to your custom output, but be able to still pass the response to the chain and ignore whatever the rest of the chain puts in the response, you could try to add the following to your wrapper :
private ServletOutputStream fakeOutputStream =
new ServletOutputStream() {
#Override
public void write(int b) throws IOException {
// do nothing. Everything written to this stream is ignored
}
}
private PrintWriter fakeWriter = new PrintWriter(fakeOutputStream);
public MyCustomResponse(String customOutput, HttpServletResponse response) {
super(response);
response.getWriter().print(customOutput);
}
#Override
public ServletOutputStream getOutputStream() {
return fakeOutputStream;
}
#Override
public PrintWriter getWriter() {
return fakeWriter;
}
I don't see the reason of what you want to do, but if you want to use your wrapper, my suggestion would be:
Create your own servlet that uses your wrapper and register it in web.xml, in something like this:
Extend javax.servlet.GenericServlet and override the service(ServletRequest, ServletResponse) method. Then you use the Template Method pattern to create a service(ServletRequest, ServletResponseWrapper). OR
Extend javax.servlet.HttpServlet and override service(HttpServletRequest, HttpServletResponse) method. Use the Template Method pattern to create a service(HttpServletRequest, HttpServletResponseWrapper). This will require that you don't use the doGet, doPost, doPut, doTrace methods already provided by HttpServlet but, instead create your own that uses your wrapper.
Hope this helps.