I am implementing rest web service using Jersey. I need to have object of ServletContext to save the file in the application directory. Please help me to get the context.
I am calling this webservice from android device.
Thanks in advance.
#Path("notice")
public class NoticeResources {
#Resource
private ServletContext context;
#POST
#Path("uploadphoto")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces("text/plain")
public String uploadNotices(#FormDataParam("file") InputStream uploadedInputStream) {
File photoDirectory = new File("\\photo");
// if the directory does not exist, create it
if (!photoDirectory.exists()) {
boolean result = photoDirectory.mkdir();
if(result){
System.out.println("DIR created");
}
}
String rootPath = photoDirectory.getAbsolutePath();
String uploadedFileLocation = rootPath + "\\photo.jpg";
// save it
try {
writeToFile(uploadedInputStream, uploadedFileLocation);
} catch(Exception e) {
return "no" + rootPath;
}
return "yes" + rootPath;
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) throws Exception {
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
}
}
Use #Context, here is Jersey documentation
#Context
private ServletContext context;
UPDATED - you can also inject directly into methods if desired
public String uploadNotices(#Context ServletContext context, ...)
use the annotation #context (Method level injection)
public Response getContext(#Context HttpServletRequest req, #Context HttpServletResponse res)throws Exception
{
System.out.println("Context Path is:"+req.getRequestURL().toString());
result=req.getRequestURL().toString();
return Response.status(200).entity(result).build();
}
Related
I have a file txt on the server (previously generated). When user clicks on button it generates the file, now I want (additionally) download the file inside my function. But I can't make it work(I'm new on JAVA EE), cause I don't know how to get HttpServletResponse.
From web I call function with this:
#Path("getreport")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject getreport(CommonInput input) {
JSONObject j = objectmapper.conertValue(reportBean.getreport(),JSONObject.class);
return j;
}
reprotBean has function:
public void getreport() {
//...doing many things
//generating my file
List<String> lines = new ArrayList<>();
lines.add("star file");
//..adding many lines
Path file = Paths.get("C:\\Users\\myuser\\file.txt");
Files.write(file, lines, StandardCharsets.UTF_8);
downloadFile();
//...doing many things
}
I found this way to download my file:
public void downloadFile(HttpServletResponse response){
String sourceFile = ""C:\\Users\\myuser\\file.txt"";
try {
FileInputStream inputStream = new FileInputStream(sourceFile);
String disposition = "attachment; fileName=outputfile.txt";
response.setContentType("text/txt");
response.setHeader("Content-Disposition", disposition);
response.setHeader("content-Length", String.valueOf(stream(inputStream, response.getOutputStream())));
} catch (IOException e) {
logger.error("Error occurred while downloading file {}",e);
}
}
private long stream(InputStream input, OutputStream output) throws IOException {
try (ReadableByteChannel inputChannel = Channels.newChannel(input); WritableByteChannel outputChannel = Channels.newChannel(output)) {
ByteBuffer buffer = ByteBuffer.allocate(10240);
long size = 0;
while (inputChannel.read(buffer) != -1) {
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
return size;
}
}
When I try to use downloadFile(), it requires HttpServletResponse, and I don't have that parameter. I can't understand how to get that (how it works), or do I have to use another method for download my file?
All solutions I found requires HttpServletResponse (download files from browsers)
If you have that file generated already. Just need write it to HttpServletResponse
resp.setContentType("text/plain");
resp.setHeader("Content-disposition", "attachment; filename=sample.txt");
try(InputStream in = req.getServletContext().getResourceAsStream("sample.txt");
OutputStream out = resp.getOutputStream()) {
byte[] buffer = new byte[ARBITARY_SIZE];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
}
Be sure to make your file to be accessed by ServeletContext
If you are using Spring Rest framework. Can refer to below
#GetMapping("/download")
public ResponseEntity<byte[]> downloadErrorData() throws Exception {
List<Employee> employees = employeeService.getEmployees();
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(employees);
byte[] isr = json.getBytes();
String fileName = "employees.json";
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentLength(isr.length);
respHeaders.setContentType(new MediaType("text", "json"));
respHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
respHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
return new ResponseEntity<byte[]>(isr, respHeaders, HttpStatus.OK);
}
credit to: https://www.jeejava.com/file-download-example-using-spring-rest-controller/
I am passing file/img(form data) from my angular app to my rest api as a post method body.
But i am not able to read inputStream content.
My Rest api method:-
#RequestMapping(path = "/upload", method = RequestMethod.POST)
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void process(#FormDataParam("file") InputStream dataStream) throws IOException {
this.writeToFile(dataStream, "src/main/resources/targetFile.jpg");
}
private void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation) {
try {
byte[] image = IOUtils.toByteArray(uploadedInputStream);
OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
IOUtils.write(image, out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
image array is always empty and hence empty file gets created in destination dir.
Anything wrong with the implementation?
You can code rest service like this.
Controller method
#RequestMapping(value="/upload", method=RequestMethod.POST)
public void handleFileUpload(#RequestParam("file") MultipartFile file){
writeToFile(file, "src/main/resources/targetFile.jpg");
}
writeToFile method
private void writeToFile(MultipartFile file, String uploadedFileLocation) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(uploadedFileLocation)));
stream.write(bytes);
stream.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
} else {
System.out.println("Empty file");
}
}
Well, i'm trying to use a FileServlet to download video from my webserver (Apache Tomcat), but this video BROKEN. I know that video is OK because if i download with FileZilla everything works fine.
See my class:
public class FileServlet extends HttpServlet {
// Constants
// ----------------------------------------------------------------------------------
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
// Properties
// ---------------------------------------------------------------------------------
private String filePath;
// Actions
// ------------------------------------------------------------------------------------
private static abstract class InnerFacesContext extends FacesContext {
protected static void setFacesContextAsCurrentInstance(
FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
private InnerFacesContext() {
}
}
public void init() throws ServletException {
// In a Windows environment with the Applicationserver running on the
// c: volume, the above path is exactly the same as "c:\files".
// In UNIX, it is just straightforward "/files".
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
this.filePath = getFacesContext(request, response).getExternalContext()
.getInitParameter("tmpDirectory");
// Get requested file by path info.
String requestedFile = request.getPathInfo();
// Check if file is actually supplied to the request URI.
if (requestedFile == null) {
// Do your thing if the file is not supplied to the request URI.
// Throw an exception, or send 404, or show default/warning page, or
// just ignore it.
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
return;
}
// Decode the file name (might contain spaces and on) and prepare file
// object.
File file = new File(filePath, URLDecoder.decode(requestedFile, "UTF-8"));
// Check if file actually exists in filesystem.
if (!file.exists()) {
// Do your thing if the file appears to be non-existing.
// Throw an exception, or send 404, or show default/warning page, or
// just ignore it.
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
return;
}
// Get content type by filename.
String contentType = getServletContext().getMimeType(file.getName());
// If content type is unknown, then set the default value.
// For all content types, see:
// http://www.w3schools.com/media/media_mimeref.asp
// To add new content types, add new mime-mapping entry in web.xml.
if (contentType == null) {
contentType = "application/octet-stream";
}
// Init servlet response.
response.reset();
response.setBufferSize(DEFAULT_BUFFER_SIZE);
response.setContentType(contentType);
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
// Prepare streams.
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open streams.
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} finally {
// Gently close streams.
close(output);
close(input);
}
}
// Helpers (can be refactored to public utility class)
// ----------------------------------------
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail
// it.
e.printStackTrace();
}
}
}
protected FacesContext getFacesContext(HttpServletRequest request,
HttpServletResponse response) {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext == null) {
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
.getFactory("javax.faces.context.FacesContextFactory");
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory("javax.faces.lifecycle.LifecycleFactory");
javax.faces.lifecycle.Lifecycle lifecycle = lifecycleFactory
.getLifecycle("DEFAULT");
facesContext = contextFactory.getFacesContext(request.getSession()
.getServletContext(), request, response, lifecycle);
InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);
javax.faces.component.UIViewRoot view = facesContext
.getApplication().getViewHandler()
.createView(facesContext, "");
facesContext.setViewRoot(view);
}
return facesContext;
}
}
PS: This class if from BalusC blog.
I have to upload a file using soap ui.Below is my service code.It executes fine if call using jersey.But when i try to call using soapui null pointer exception occurs.
I call the fileupload service in soap ui like below
Create Rest Project:
Add the Url:
http://localhost:8080/FileService/Services/HomeService/testupload
file file:c:\\1.wav
#POST
#Path("testupload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_PLAIN)
public String uploadFile(#FormDataParam("file") InputStream fis,
#FormDataParam("file") FormDataContentDisposition fdcd) {
OutputStream outpuStream = null;
String fileName = fdcd.getFileName();
String filePath = FOLDER_PATH + fileName;
try {
int read = 0;
byte[] bytes = new byte[1024];
outpuStream = new FileOutputStream(new File(filePath));
while ((read = fis.read(bytes)) != -1) {
outpuStream.write(bytes, 0, read);
}
outpuStream.flush();
outpuStream.close();
} catch(IOException iox){
iox.printStackTrace();
} finally {
if(outpuStream != null){
try{outpuStream.close();} catch(Exception ex){}
}
}
return "File Upload Successfully !!";
}
How to fix this issue? Any help will be greatly appreciated!!!
I am writing a small file upload utility thing as part of a larger project. Originally I was handling this from a servlet using the Apache commons File utility classes. Here is a snippet from a quick test client I wrote for the service:
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(FileUploadService.class);
factory.setAddress("http://localhost:8080/FileUploadService/FileUploadService");
FileUploadService client = (FileUploadService) factory.create();
FileType file = new FileType();
file.setName("statemo_1256144312279");
file.setType("xls");
DataSource source = new FileDataSource(new File("c:/development/statemo_1256144312279.xls"));
file.setHandler(new DataHandler(source));
Boolean ret = client.uploadFile(file);
System.out.println (ret);
System.exit(0);
}
This works absolutely fine. Now the problem comes when I am trying to replace the Apache commons utilities. In the above code I am creating a DataSource from a File with an absolute path name. In my servlet, I can't get an absolute path name however and the file I am sending over the wire is empty.
Here is the servlet code:
#SuppressWarnings("unchecked")
protected void doPost (final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
// form should have enctype="multipart/form-data" as an attribute
if (!ServletFileUpload.isMultipartContent (request)) {
LOG.info("Invalid form attribute");
return;
}
//DataInputStream in = new DataInputStream(request.getInputStream());
final DiskFileItemFactory factory = new DiskFileItemFactory ();
factory.setSizeThreshold(FILE_THRESHOLD_SIZE);
final ServletFileUpload sfu = new ServletFileUpload (factory);
sfu.setSizeMax(MAX_FILE_SIZE);
final HttpSession session = request.getSession();
final List<FileItem> files = new ArrayList<FileItem>();
final List<String> filesToProcess = new ArrayList<String>();
try {
final List<FileItem> items = sfu.parseRequest(request);
for (final FileItem f : items) {
if (!f.isFormField())
files.add(f);
}
/*for (final FileItem f : files) {
final String absoluteFileName = UPLOAD_DESTINATION + FilenameUtils.getName(f.getName());
//f.write(new File (absoluteFileName));
filesToProcess.add(absoluteFileName);
}*/
FileItem f = files.get(0);
LOG.info("File: " + FilenameUtils.getName(f.getName()));
LOG.info("FileBaseName: " + FilenameUtils.getBaseName(f.getName()));
LOG.info("FileExtension: " + FilenameUtils.getExtension(f.getName()));
FileUploadServiceClient client = new FileUploadServiceClient();
DataSource source = new FileDataSource(new File(f.getName()));
FileType file = new FileType();
file.setHandler(new DataHandler(source));
file.setName(FilenameUtils.getBaseName(f.getName()));
file.setType(FilenameUtils.getExtension(f.getName()));
Boolean ret = client.uploadFile(file);
LOG.info("File uploaded - " + ret);
filesToProcess.add(UPLOAD_DESTINATION + FilenameUtils.getName(f.getName()));
session.setAttribute("filesToProcess", filesToProcess);
final RequestDispatcher dispatcher = request.getRequestDispatcher("Validate");
if (null != dispatcher) {
dispatcher.forward(request, response);
}
} catch (FileUploadException e) {
LOG.info("Exception " + e.getMessage());
e.printStackTrace();
} catch (Exception e) {
LOG.info("Exception " + e.getMessage());
e.printStackTrace();
}
}
I've been working on this for the better part of this morning and am not getting anywhere. Even if I get rid of the Apache commons file stuff completely and handle the parsing of the request myself, I still can't construct the DataSource appropriately.
Thanks!
This was rather simple actually, I just copied over the bytes from the InputStream to the DataSource:
FileItem f = files.get(0);
// there is a problem here where the file being created is empty, since we only have a
// partial path:
DataSource source = new FileDataSource(new File(f.getName()));
// because of the above problem, we are going to copy over the data ourselves:
byte[] sourceBytes = f.get();
OutputStream sourceOS = source.getOutputStream();
sourceOS.write(sourceBytes);
This is the code of commons-email ByteArrayDataSource
it sounds odd to try to replace apache commons - don't, unless you have a really good reason
you can get absolute paths in a servlet. You can call getServletContext().getRealPath("/") which will return the absolute path of your application, and then you can get files relative to it.
In our application there are objects that have properties InputStream and Name. We are using next class to construct DataSource with those properties.
public class InputStreamDataSource implements DataSource {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final String name;
public InputStreamDataSource(InputStream inputStream, String name) {
this.name = name;
try {
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
inputStream.close();
buffer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public String getContentType() {
return new MimetypesFileTypeMap().getContentType(name);
}
#Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(buffer.toByteArray());
}
#Override
public String getName() {
return name;
}
#Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read-only data");
}
}
Most of the solutions shown here require that the InpustStream be closed (read into memory). It is possible to wrap the InputStream in a DataSource object without closing the InputStream though:
private record PipedDataSource(InputStream in, String contentType, String encoding)
implements DataSource, EncodingAware {
public String getContentType() {
return contentType;
}
public InputStream getInputStream() {
return in;
}
public String getName() {
return "PipedDataSource";
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("No OutputStream");
}
#Override
public String getEncoding() {
return encoding;
}
}
The example above also implements EncodingAware. This can prevent the InputStream from being closed by third part libraries (for example java.mail.internet.MimeUtility) when they get the data source encoding.