Java - Sending file over HTTP Server - java

I made a HTML server using com.sun.net.httpserver library. I want to send a jar file to the client to make them download it.
This method below actually make the client download the file:
#Override
public void handle(HttpExchange httpExchange) {
File file = new File("Test.jar");
try {
httpExchange.sendResponseHeaders(200, file.length());
OutputStream outputStream = httpExchange.getResponseBody();
Files.copy(file.toPath(), outputStream);
outputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
but it sends the jar file as a zip. How do I get it to send it as a jar file instead? And is there a better way to send files?

Please try adding the following to get correct filename for the download:
httpExchange.getResponseHeaders().add("Content-Disposition", "attachment; filename=Test.jar");
You might also want do add the following to get the corrent content-type:
httpExchange.setAttribute(HTTPExchange.HeaderFields.Content_Type.toString(), "application/java-archive");
Please see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types for a listing of content-types for different suffixes.

Related

Uploaded file fails to save with no exception thrown in Java - Jersey

I'm trying to upload a file to a restful - Jersey web service deployed on Tomcat server that is a receives uploaded files as multipart . It works fully correct on Windows OS but on Linux the file fails to save with no exception thrown from the following saving method :
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadProductImage(
#FormDataParam("file") final InputStream uploadedInputStream,
#FormDataParam("file") final FormDataContentDisposition cdh,
#FormDataParam("file") final FormDataBodyPart body
) {
FileManager fileManager = new FileManager();
String fileName;
try {
int read = 0;
byte[] bytes = new byte[1024];
OutputStream out = new FileOutputStream(new File("/home/files"));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return Response.status(Response.Status.CREATED).entity(gson.toJson(cdh.getName())).build();
}
The multipart variable is already declared in the web.xml file as :
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
As seen in the code the target path is "/home/files".
I'm sure that the path exists and I already tried to change the owner of the target file to the tomcat group , and granted all the permissions to the path without any results.
I appreciate your help.
So after working on this I found out that file write fails or permission errors are not thrown as exceptions , the code would work normally , and in this case what can be done to solve this type of problem is the following:
Since the path is outside the war body it has to be indicated to within the server.xml file in the tomcat directory.
The directory group has to be same as Tomcat group , it can be changed through chgrp command in linux terminal.
Permission has to be granted to the directory's group using the chmod command in linux.

Unable to download file from swagger

#ApiResponses(value = {
#ApiResponse(code = 200, message = "Perfect") })
public void getLabel(#QueryParam("orderItemsId") String orderItemsId,HttpServletRequest httpServletRequest,HttpServletResponse response) {
String dataDirectory = httpServletRequest.getSession().getServletContext().getRealPath("/WEB-INF/files/label.pdf");
Path file = Paths.get(dataDirectory);
if (Files.exists(file))
{
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename=\"label.pdf\"");
try
{
Files.copy(file, response.getOutputStream());
response.getOutputStream().flush();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
I am using springfox-swagger2 - version 2.5.0 with springfox-swagger-ui - version 2.5.0.
without content-Disposition header swagger is unable to sync output file in swagger-ui, it shows data in binary form(i guess)kind-of corrupted and whereas with this header i get a link in ResponseBody which also downloads pdf but corrupted form same as it syncs in swagger-ui.
I have done a research it shows we need to provide datatype:"file" in response link . but #ApiResponse doesn't contain any datatype field. Though it has field with response but i am not sure what class to give for
octet-stream output. I have tried OutputStream but it doesn't work.
Edit : Swagger UI does not support the downloading of file. whereas same url if called through other source will do the job.
Swagger UI does not support the downloading of file. whereas same url if called through other source will do the job.

How can I download a file which I have dynamically created on Apache TomCat Server?

I created an ".xlsx" file (CustomerData.xlsx) by using "Apache POI".
The problem is that the file is created on my TomCat Server and I have to download it.
I tried the following code, in order to download the file:
HttpServletResponse response = null;
response.setContentType("xlsx");
response.setHeader(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"attachment; filename=C:\CustomerData.xlsx");
try {
workbook.write(response.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
but unfortunately, it does not seem to work.
In case you have any idea or suggestion, do not hesitate posting it.
You mix content type and attachment information into a single header which cannot work.
Instead write
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=CustomerData.xlsx");

Download a file through Spring MVC controller using streams

I am using spring MVC with REST service for one of my project. I am having a service to attach and download user files.
I am using below service API for upload and save file into server directory
http://myrestserver/attachmentService/attach/userKey
And below service API for download files from server directory
http://myrestserver/attachmentService/download/userKey/fileKey
The issue is that when a file is downloaded, the downloaded URL shows the REST service API URL. To avoid this, I thought of write a controller for attach and download file.
I wrote a spring controller which handle file attachment process. Even I wrote a controller(say download.do) for download a file, but when a file downloaded, the file name shows as the same name of the controller(downloaded file name shows "download.do" always) instead of original file name.
Below code is from my download.do controller
WebResource resource = null;
resource = client.resource("http://myrestserver/attachmentService/download/userKey/fileKey");
clientResponse = resource.accept(MediaType.APPLICATION_OCTET_STREAM).get(
ClientResponse.class);
InputStream inputStream = clientResponse.getEntityInputStream();
if(inputStream != null){
byteArrayOutputStream = new ByteArrayOutputStream();
try {
IOUtil.copyStream(inputStream, byteArrayOutputStream);
} catch (IOException e) {
log.error("Exception in download:"+ e);
}
}
And, in my service API, the code is
file = new File(directory, attachmentFileName);
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(attachmentContent);
fileOutputStream.close();
response = Response.ok((Object) file).type(MediaType.APPLICATION_OCTET_STREAM);
response.header("Content-Disposition", "attachment; filename=" + "\"" + attachmentFileName
+ "\"");
return response.build();
By analyzing the issue, I understood that, am not setting file header in downloaded file through download.do controller.
If I am using outstream in download.do controller, I will not be able to set the file header.
Can any one help me to resolve this issue. My primary aim is to hide my rest service URL from downloaded file by stream through a MVC controller.
I found a post (Downloading a file from spring controllers )in stack overflow almost like my question, but the file type is previously known. Please note that, in my application user can attach any type of file.
You have to set the Content-Disposition prior to writing the file to the output stream. Once you start writing to the output stream, you cannot set headers any longer.

Reading file from FTP URL in Google App Engine, FileNotFoundException

I'm writing code to read a file from an FTP URL in order to parse it and store the data in Google App Engine's Datastore. I'm able to get the code working fine when reading test files hosted on my own web server, however when I try to read the data file I need I'm getting a FileNotFoundException.
I'm able to use the same FTP URL in a browser to download the file, and can anonymously connect to the FTP URL in FileZilla, so access shouldn't be a problem, and the file is definitely there. It's a pretty big file, but I've tried to grab smaller files from the same FTP server with no luck either.
Here's the code I have at the moment:
public void doGet(HttpServletRequest req,
HttpServletResponse resp) throws IOException, ServletException {
// works with a URL to my own server & a test.zip, but not this one
final URL url = new URL(
"ftp://gisftp.metc.state.mn.us/google_transit.zip");
// without the privileged action, I get an AccessControlException
ZipInputStream zin = AccessController.doPrivileged(
new PrivilegedAction<ZipInputStream>() {
public ZipInputStream run() {
return getZipStream(url);
}
}
);
ZipEntry zipentry = zin.getNextEntry();
// processing files here
zin.close();
}
// but using the privileged method, we get a FileNotFoundException
public ZipInputStream getZipStream(URL url) {
ZipInputStream zipin = null;
try {
zipin = new ZipInputStream(url.openStream());
} catch (IOException e) {
e.printStackTrace();
}
return zipin;
}
At first I was getting an AccessControlException, but using a PrivilegedAction to open the stream seems to fix that.
I don't have access to the server where the file is stored, so can't change anything there.
I think there is a restriction on the ports that can be connected to from App Engine and FTP (21) is not in the list, this maybe causing the issue. From the URL Fetch documentation;
An app can fetch a URL using HTTP (normal) or HTTPS (secure). The URL specifies the scheme to use: http://... or https://...
The URL to be fetched can use any port number in the following ranges: 80-90, 440-450, 1024-65535. If the port is not mentioned in the URL, the port is implied by the scheme: http://... is port 80, https://... is port 443.

Categories