JAX-RS file downloads, multiple content types
Solution 1
You could use application/octet-stream
as content type and do the following to download files:
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(String fileName) {
File file = ... // Find your file
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"")
.build();
}
Since you are using JavaScript to download files, have a look here and here.
Solution 2
Fixed it, used the content-type: application/octet-stream. I also added the header mentioned above:
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"")
.build();
my error was thinking that after an ajax call the file would download in the same window. changed my client side code to do the request in another window using :
window.open(resturl);
the reaction was that the browser would open a new window, download the file into the download tray and return to the webpage in which you clicked download whilst closing the download tab. (in about 0.2 seconds).
Mark Stroeven
Hey there, My name is Mark, I am a full time IT student wanting to specialize in programming. Still learning a lot and thought i could learn a lot from more experienced programmers around here! You will have to excuse me for my bad limited English, I am afraid it is not my native language.
Updated on June 04, 2022Comments
-
Mark Stroeven almost 2 years
Let me provide some context first. I am working on a system that integrates with Microsoft SharePoint 2010, well not really SharePoint as a system but the virtual representation of it's filesystem, document libraries, etc... Users upload files to SharePoint, and my system monitors these files and indexes them into a search engine (including file content). User can interact with this system by means of REST interfaces.
I have created a REST interface to fetch a file for the user corresponding a certain entry in my search engine. This uses the absolute network path as its identifier. An example would be
//corporateserver//library1/filex.docx
. Due to the same origin policy however I can not load this file client side. Therefore I am trying to transmit it via the server.I had some success using JAX-RS to transmit data, however, I am getting stuck at the following:
The file the user wishes to download can be of mutliple content types, most of them will be microsoft office formats. I had a look through the list of registered MIME types and came across
application/msword
orapplication/vnd.ms-powerpoint
My question: is there a content type that would include Microsoft Office files? If not, how could one proceed to match the correct content types with a file that is being requested. What would happen if one would server a word file with content type
text/plain
?Any help on the subject would be greatly appreciated.
EDIT
The code I use to transmit data:
package com.fujitsu.consensus.rest; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.IOUtils; import org.codehaus.jettison.json.JSONException; @Path("/fetcher") public class FetcherService { @GET @Path("/fetch") @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response fetchFile(@QueryParam("path") String path) throws JSONException, IOException { final File file = new File(path); System.out.println(path); StreamingOutput stream = new StreamingOutput() { @Override public void write(OutputStream output) throws IOException { try { output.write(IOUtils.toByteArray(new FileInputStream(file))); } catch (Exception e) { e.printStackTrace(); } } }; return Response.ok(stream, MediaType.APPLICATION_OCTET_STREAM) .header("Content-Disposition", "inline; filename=\"" + file.getName() + "\"") .build(); } }
JavaScript code:
$.ajax({ url: "../rest/fetcher/fetch", type: "GET", //send it through get method data:{path:obj.id}, success: function(response) { console.log(response);}, error: function(xhr) {//Do Something to handle error} });
The response I get on client side:
EDIT 2
I've added a HTTP trace as proof that the headers and data are in fact being transmitted, the download dialogue however is not shown.
The
Content-Disposition
header does not appear to be working with either inline or attachment. -
Mark Stroeven over 8 yearsadded some more info, came a bit further but still not working as intended with the code example provided.
-
cassiomolin over 8 years@MarkStroeven The response seems fine, since you are downloading a file. The problem might be in the JavaScript you are using. For test purposes, try using
GET
instead ofPOST
, send the file name as a query or path parameter and type the URL in the browser instead of using JavaScript. -
cassiomolin over 8 years@MarkStroeven Have a look at my updated answer about downloading files with JavaScript.
-
Mark Stroeven over 8 yearsTried both of the threads you linked :) both are giving the error "Not allowed to load local resource" both server and client are actually on the same corporate domain.
-
cassiomolin over 8 years@MarkStroeven Can you download the file using
GET
and typing the URL in the browser address bar? -
Mark Stroeven over 8 yearsTested it using the file location as a parameter with a get request. I fetches the data, if I print it you see the encoded data again. Its not prompting a download screen. Same thing when I enter it manually.