Stephen D
Stephen D

Reputation: 3076

Why are my headers null after a POST?

I'll lay down my code first: Note: I also have log output at the bottom of the question.

Server Side:

@Post
@Consumes("application/octet-stream")
public Representation post(InputStream zip, @HeaderParam(value = "Content-Disposition") HttpHeaders headers) throws Throwable {
    System.out.println(headers); //Prints null - want the header to not be null here
    String uploadedFileLocation = getStartingDir() + "/" + "abc.zip";
    writeToFile(zip, uploadedFileLocation); 
    return new StringRepresentation("Uploaded!");
}

Client Side:

public static void main(String[] args) throws Exception {
    final String BASE_URI = "http://localhost:8080/server/upload";

    Client client = Client.create();
    WebResource service = client.resource(BASE_URI);
    client.setChunkedEncodingSize(1024);
    client.addFilter(new LoggingFilter());


    File zip = new File("C:/Users/sdery/Desktop/abc.zip");

    InputStream fileInStream = new FileInputStream(zip);
    String sContentDisposition = "attachment; filename=\"" + zip.getName()+"\"";     
    ClientResponse response = service.header("Authorization", "Basic xxx=").header("Content-Disposition", (Object)sContentDisposition).type(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class, fileInStream);     
    System.out.println("Response Status : " + response.getEntity(String.class));

}

First off, the file transfer works, I'm happy. However, I would like to get the headers on the server side so I don't have to hard code the file name. Any ideas as to why it is comin' up null? Does it have to do with me using ClientResponse instead of ClientRequest?

Jul 31, 2013 8:44:12 AM com.sun.jersey.api.client.filter.LoggingFilter log
INFO: 1 * Client out-bound request
1 > POST http://localhost:8080/server/upload
1 > Content-Disposition: attachment; filename="abc.zip"
1 > Authorization: Basic xxx=
1 > Content-Type: application/octet-stream

(zip bytes)

INFO: 1 * Client in-bound response
1 < 200
1 < Date: Wed, 31 Jul 2013 12:44:12 GMT
1 < Date: Wed, 31 Jul 2013 12:44:12 GMT
1 < Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
1 < Content-Length: 88
1 < Set-Cookie: rememberMe=deleteMe; Path=/server; Max-Age=0; Expires=Tue, 30-Jul-2013   12:44:12 GMT
1 < Content-Type: text/plain; charset=UTF-8
1 < Accept-Ranges: bytes
1 < Server: Restlet-Framework/2.0.4
1 < Real-Token: bar
1 < 
Uploaded!

From the log output, it seems that the header containing Content-Disposition is there. Does this mean I should be able to retrieve the value from the server side code?

Upvotes: 0

Views: 3515

Answers (2)

Lochemage
Lochemage

Reputation: 3974

First off, I apologize that my solution is from a JavaScript/PHP reference and not Java, but I believe your solution may be similar.

Add a new header named 'X-FILENAME' and set the name of your file as the header data. I believe your code would look something like this:

ClientResponse response = service.header("X-FILENAME", "abc.zip");

Then, on your server, you should be able to retrieve that header param (In PHP it is the $_SERVER global, it looks like in yours it may be @HeaderParam).

Also, for reference just in case this applies to you, in PHP when you retrieve the header param you need to use a modified param name by adding 'HTTP_' to the front and changing all dashes to underscores like this 'HTTP_X_FILENAME'. So on the client you sent 'X-FILENAME' while on the server you retrieve that same value with 'HTTP_X_FILENAME'.

I hope this leads you in the right direction.

Upvotes: 0

Michael Krussel
Michael Krussel

Reputation: 2656

You're parameter is of the wrong type. You should declare the parameter as a String. HttpHeaders is for getting all the headers and is annotated with a @Context. @HttpParam can only be converted to a limited number of types.

From the Jersey documentation for HeaderParam.

Binds the value(s) of a HTTP header to a resource method parameter, resource class field, or resource class bean property. A default value can be specified using the DefaultValue annotation. The type T of the annotated parameter, field or property must either:

Be a primitive type
Have a constructor that accepts a single String argument
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String))
Be List<T>, Set<T> or SortedSet<T>, where T satisfies 2 or 3 above. The resulting collection is read-only.

So you're code would be more like

@Post
@Consumes("application/octet-stream")
public Representation post(InputStream zip, @HeaderParam(value = "Content-  Disposition") String contentDisposition) throws Throwable {
   System.out.println(contentDisposition); 
   String uploadedFileLocation = getStartingDir() + "/" + "abc.zip";
   writeToFile(zip, uploadedFileLocation); 
   return new StringRepresentation("Uploaded!");
}

Upvotes: 1

Related Questions