I'm working on a web app (Java/JSP) and part of it, is to allow users to download the requested file only "Once". The problem that when they hit "Download" button, they will be asked to save/open or cancel the file and whatever they respond the file will be marked as downloaded and the user won't be able to download it again.
I'm trying to figure out a way to not count the file as downloaded when the user respond with "Cancel" and to check if really the user downloaded the file completely.
Here is the Java Part:
#WebServlet("/download")
public class download extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_BUFFER_SIZE = 10240;
/**
* #see HttpServlet#HttpServlet()
*/
public download() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Class.forName("org.sqlite.JDBC");
Connection c = DriverManager.getConnection("jdbc:sqlite:C:\\sqlite\\mascapp.db");
c.setAutoCommit(false);
Cookie[] cookies = request.getCookies();
if(request.getSession().getAttribute("aeid") == null || request.getSession().getAttribute("uid") == null)
{
response.sendRedirect("/index.jsp");
}
int ae_num = Integer.parseInt(request.getSession().getAttribute("aeid").toString());
String sql = "SELECT file, filename FROM reports INNER JOIN download USING(tipid) WHERE reports.tipid = ?"+
"AND download.ts_" + ae_num+ " = 0;";
PreparedStatement stmt = c.prepareStatement(sql);
String tipNum = request.getParameter("tipid");
if (tipNum != null) {
stmt.setString(1, tipNum);
//stmt.setString(2, tipNum);
ResultSet res = stmt.executeQuery();
BufferedInputStream fileBlob = null;
String filename = "";
while (res.next()) {
fileBlob = new BufferedInputStream(res.getBinaryStream("file"), DEFAULT_BUFFER_SIZE);
filename = res.getString("filename");
}
if (fileBlob != null) {
System.out.println(filename);
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
BufferedOutputStream output = new BufferedOutputStream(response.getOutputStream(),
DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = fileBlob.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.close();
fileBlob.close();
Date now = new Date();
sql = "UPDATE download SET ts_" + ae_num + " = " + now.getTime() + " WHERE tipid = ?;";
System.out.println(sql);
stmt = c.prepareStatement(sql);
stmt.setString(1, tipNum);
stmt.executeUpdate();
stmt.close();
c.commit();
c.close();
}
else
{
c.close();
response.sendRedirect("/MASC/formdownloaded.jsp");
}
}
else
{
response.getWriter().append("<html><body><h1>Error: no param</h1></body></html>");
c.close();
}
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Any solution or suggestion?! Thank you in advance.
Check this page: http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/ (this link doesn't work sometimes, if you have some problems with it here is a link to github: https://github.com/johnculviner/jquery.fileDownload ).
It looks like the best you can do here is to make sure that download was started by checking on client side special cookie sent back from server with downloading file stream. For that you have to add Cookie into servlet response like in this thread:
Set cookie only after file download complete.
So at the end of doGet method in your servlet you should have something like:
Cookie fileDwnld = new Cookie("fileDownload", "true");
fileDwnld.setPath("/");
response.addCookie(fileDwnld);
And here is client side code:
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="jquery.fileDownload.js"></script>
<script>
$(document).ready(function() {
$("#btnSubmit").click(function(){
$.fileDownload('path/to/servlet')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
});
});
The answer is don't do that. Those dialogs are there for good reasons, some of them involving security.
What you want to do instead depends on why you only want the user to download the file once. Downloads can fail for all sorts of reasons, so what are you going to do if the user loses their connection in the middle of the download?
I don't have a proper answer, but I do know that the "attachment;" in the header forces the browser to "download" the file, compared to "open it", if you understand what I mean. Try removing that header and see if you get the desired effect.
Related
am new to servlet and jsp.. I am able to generate and export excel file from database in java swing. I wrote same code in servlet and i get 0 bytes after a prompt to download.
i cant seem to figure out what i left out.
#WebServlet(name = "excel_purchases", urlPatterns = {"/excel_purchases"})
public class excel_purchases extends HttpServlet {
PreparedStatement pst=null; ResultSet rs=null;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try (PrintWriter out = response.getWriter()) {
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment; filename=purchases.xlsx");
/* TODO output your page here. You may use following sample code. */
try{
con = C3p0DataSource.getInstance().getConnection();
String sql = "select shop,item,date,id,source_name,quantity,unit,price,grand_total from purchase_print";
pst=con.prepareStatement(sql);
rs=pst.executeQuery();
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet("purchases");
XSSFRow rowhead;
rowhead = sheet.createRow(0);
rowhead.createCell(0).setCellValue("Shop");
rowhead.createCell(1).setCellValue("Product");
rowhead.createCell(2).setCellValue("Date");
rowhead.createCell(3).setCellValue("Num");
rowhead.createCell(4).setCellValue("Source Name");
rowhead.createCell(5).setCellValue("Qnty");
rowhead.createCell(6).setCellValue("U/M");
rowhead.createCell(7).setCellValue("Cost Price");
rowhead.createCell(8).setCellValue("Amount");
int i = 1;
while(rs.next()){
XSSFRow row= sheet.createRow((short)i);
row.createCell(0).setCellValue(rs.getString("shop"));
row.createCell(1).setCellValue(rs.getString("item"));
row.createCell(2).setCellValue(rs.getString("date"));
row.createCell(3).setCellValue(rs.getDouble("id"));
row.createCell(4).setCellValue(rs.getString("source_name"));
row.createCell(5).setCellValue(rs.getDouble("quantity"));
row.createCell(6).setCellValue(rs.getString("unit"));
row.createCell(7).setCellValue(rs.getDouble("price"));
row.createCell(8).setCellValue(rs.getDouble("grand_total"));
i++;
}
workbook.write(response.getOutputStream());
}
}catch(SQLException | IOException e){
out.println(e);
}
response.sendRedirect("purchases_sect/purchases_search.jsp");
//set download format
}
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
when i click on this button in a jsp page..,
<button formaction="excel_purchases" formmethod="post">export to excel</button>
it does download but the excel file is empty. the file size is indicated as 0 bytes during download.
I have implemented drag & drop file uploading in jsp and servlet, but I have a problem. Here is a part of my upload.jsp code:
function dropUpload(event) {
var files = event.dataTransfer.files;
upload(files);
}
function upload(files) {
var formData = new FormData();
for (var i in files) {
formData.append('file[]', files[i]);
}
var xhr = new XMLHttpRequest();
xhr.onload = function() {
console.log(xhr.responseText);
};
xhr.open("POST", "UploadServlet");
xhr.send(formData);
}
I use the getParts() method in my UploadServlet.java code to get the files that the user uploads, like below:
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public UploadServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("login.jsp").forward(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String savePath = "D:\\TEST";
// creates the save directory if it does not exists
File fileSaveDir = new File(savePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdir();
}
response.getWriter().println(request.getParts().size());
for (Part part : request.getParts()) {
if(part.getContentType() == null) {
continue;
}
response.getWriter().println("Part name: " + part.getName());
response.getWriter().println("Size: " + part.getSize());
response.getWriter().println("Content Type: " + part.getContentType());
String fileName = extractFileName(part, response);
response.getWriter().println(fileName);
part.write(savePath + File.separator + fileName);
response.getWriter().println("already upload file:" + fileName);
response.getWriter().println("=============================================");
}
}
private String extractFileName(Part part,HttpServletResponse response) throws IOException {
String contentDisp = part.getHeader("content-disposition");
//response.getWriter().println(contentDisp);
String[] items = contentDisp.split(";");
for (String s : items) {
if (s.trim().startsWith("filename")) {
return s.substring(s.indexOf("=") + 2, s.length()-1);
}
}
return "";
}
But I can't understand that if I upload 2 files with upload.jsp,
the value of getParts().size() is 4; it means that I always have 2 more files than exactly what I upload, and the 2 external files name and contentType will be null, and it will cause an error in part.write().
My solution is use the if statement
if(part.getContentType() == null) {
continue; }
to ignore the null file.
Can somebody tell me why this happens?
I'd like to invoke IBM Bluemix service (say Text to Speech) from my Java code.
I've managed to get service credentials and URL but how can I invoke it after?
I've seen some example where people have used similar to below code but wondering how it works for a Text to Speech where it outputs a wav stream.
String profileString = ex.execute(profileRequest)
.handleResponse(new ResponseHandler<String>() {
#Override
public String handleResponse(HttpResponse r)
throws ClientProtocolException, IOException {
}
}
Can any one suggest on priority please?
The link below has a Java code example of how to use the Watson text-to-speech service.
https://github.com/watson-developer-cloud/text-to-speech-java
You should be looking for something like this from the DemoServlet.java class:
#Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
if (req.getParameter("text") == null || req.getParameter("voice") == null) {
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} else {
boolean download = false;
if (req.getParameter("download") != null && req.getParameter("download").equalsIgnoreCase("true")) {
download = true;
}
req.setCharacterEncoding("UTF-8");
try {
String queryStr = req.getQueryString();
String url = baseURL + "/v1/synthesize";
if (queryStr != null) {
url += "?" + queryStr;
}
URI uri = new URI(url).normalize();
Request newReq = Request.Get(uri);
newReq.addHeader("Accept", "audio/ogg; codecs=opus");
Executor executor = Executor.newInstance().auth(username, password);
Response response = executor.execute(newReq);
if (download)
{
resp.setHeader("content-disposition", "attachment; filename=transcript.ogg");
}
ServletOutputStream servletOutputStream = resp.getOutputStream();
response.returnResponse().getEntity()
.writeTo(servletOutputStream);
servletOutputStream.flush();
servletOutputStream.close();
} catch (Exception e) {
// Log something and return an error message
logger.log(Level.SEVERE, "got error: " + e.getMessage(), e);
resp.setStatus(HttpStatus.SC_BAD_GATEWAY);
}
}
}
Finally, the link below has instructions on how to create a Java war file and deploy to Bluemix:
https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/getting_started/gs-full-java.shtml
Hello all i have write this servlet to doGet data and Client-side can get some information from database after query and
pointer but when i send a pointer to servlet from client-side there
are no response and http code is 204 can any one help me with that?
thanks
//This Servlet Make User To Get Data from Database (data) Table (replay) Fileds (Callreplay,State)
package server;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
*/
#WebServlet(name = "GetStatus", urlPatterns = {"/GetStatus"})
public class GetStatus extends HttpServlet
{
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public GetStatus()
{
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// getting id as parameter
String strID;
strID = request.getParameter("newid");
System.out.println("* Pointer is "+strID);
// connecting to the database
GetStatusFromDB dbManager = new GetStatusFromDB();
dbManager.iniDBManagementLayer("jdbc:mysql://127.0.0.1:3306/data",
"root",
""
);
//System.out.println("** Connection with database OK!");
// getting data from the database
String sql = "SELECT * FROM replay WHERE S_id = " + strID + ";";
dbManager.setFields("status", "comment");
dbManager.sendQuery(sql);
String resp = dbManager.getJSON();
System.out.println("*** Mutaz Method Ok!");
if(resp != null)
{
System.out.println(resp);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json; charset=utf-8");
response.getWriter().print(resp);
// System.out.println("Get Ok !");
}
else
{
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
public void sendQuery(String query) {
// Connection, statement, and ResultSet should not defined as instances
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
InitialContext ctx = new InitialContext();
DataSource ds =
(DataSource)ctx.lookup("java:comp/env/jdbc/jndipool");
conn = ds.getConnection();
st = conn.prepareStatement(query);
rs = st.executeQuery();
processResults(rs);
} catch (NamingException ex) {
// Logger.getLogger(DBManagementLayer.class.getName()).log(Level.SEVERE, null, ex);
this.errorFlag = true;
this.lastError = ex.toString();
} catch (SQLException ex) {
this.errorFlag = true;
this.lastError = ex.toString();
}
finally{
if ( rs != null ) {
try { rs.close(); rs = null;}
catch (SQLException e) {
errorFlag = true; lastError = e.toString(); }
}
Http response code 204 is what is being set by this line
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
So it's likely that dbManager.getJSON() is returning null.
**in this line i most add
try
{
////here most add rs.first();
Gson conv = new Gson();
String status = rs.getString(fieldOne);
String comment = rs.getString(fieldTwo);
String rep = conv.toJson(new StatusForm(status, comment ));
this.statusAsJSON = rep;
} catch (SQLException ex) {
Logger.getLogger(GetStatusFromDB.class.getName()).log(Level.SEVERE, null, ex);
}
this must add
boolean first = rs.first();
and it will be fixed
thanks for evrey body here help me thanks for all programmers here thank you stackoberflow.com Max**
Im using a servlet that connects to a database and prints out whether or not you are logged in or not, When using printWriter.write(JsonObject) i get the error in rest Unexpected Token L. I am using a tomcat server to host the data.
public class Login extends HttpServlet {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/employeedatabase";
// Database credentials
static final String USER = "root";
static final String PASS = "admin";
static Connection conn = null;
static Statement stmt = null;
static ResultSet rs;
static PrintWriter out;
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Login() {
super();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json; charset=UTF-8");
out = response.getWriter();
String email = request.getParameter("username");
String password = request.getParameter("password");
String result = "";
if(Validation.validateNull(email) && Validation.validateNull(password)){
if(!Validation.validateEmail(email))
{
result = "Invalid email";
}
if(databaseFuctions.Login(email,password))
{
result = "Login accepted";
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
getFromDatabase("manager",email,request,response);
// getFromDatabase("qa",email,request,response);
// getFromDatabase("developer",email,request,response);
} catch (Exception e1) {
// TODO Auto-generated catch block
System.out.println(e1.getMessage());
}
}
else if(!databaseFuctions.Login(email, password))
{
result = "Login invalid";
}}
else{
result = "No login/password entered";
}
out.write(result);
}
public static void getFromDatabase(String table,String email,HttpServletRequest request, HttpServletResponse response){
JSONObject JObject = new JSONObject();
ResultSet ds;
try {
ds = stmt.executeQuery("SELECT * from "+table+" where email = '"+email+"'");
while(ds.next())
{
int id = ds.getInt("id");
int salary = ds.getInt("salary");
String name = ds.getString("name");
String role = ds.getString("role");
String emailAddress = ds.getString("email");
String phone = ds.getString("phone");
JObject.put("id", id);
JObject.put("salary", salary);
JObject.put("name", name);
JObject.put("role", role);
JObject.put("email", emailAddress);
JObject.put("phone", phone);
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
out.print(JObject.toString());
out.flush();
System.out.println(JObject.toString());
}
When printing in the system i get all the correct data, or checking the raw data from rest i get the correct data. But i dont quite understand why the printer is throwing the exception any help is amazing
Ok If the error is in the client is beacuse you are returning a mal formed JSON value, so you are returning something like that: { id: 13, name: "Name"}Login invalid then the first character the L is not valid for the JSON Syntax.
This is becuase you are writing in the response the json string from the method getFromDatabase out.print(JObject.toString()); and after the method call you add to the response the string result = "Login invalid"; out.write(result); that cause you have a invalid JSON.
One way to solve this is return the JSONObject from the method getFromDatabase, and add the put the result method in this object JObject.put("result", result) and the write the object to the response.