views:

3565

answers:

3

Hi there,

I'm trying to craete a site which allows users to upload any file type they like. I've implemented this feature fine, and the file is held on the server. Later on they can download the file to view, but i'm having trouble getting it to work.

I've used any examples I can get hold of but they all tend to use text files as examples. My problem is that pdf's and many other file types aren't downloading properly. They seem to download fine, but none of the files will open successfully. Comparing the files, it seems most of the files content is correct, but certain parts are not.

Here's my groovy code:

def file = new File(params.fileDir)    
response.setContentType("application/octet-stream")
response.setHeader("Content-disposition", "filename=${file.getName()}")
response.outputStream << file.text
return

This code is held inside a controller which is called by a download link. I've tried playing around with different contentTypes, but I don't know which I could use for any type - is there one? Anything I try doesn't solve the problem.

Thanks for your help.

+14  A: 

The problem is that you read the content of the file into a String by using "file.text". The content of the file is converted with the system character encoding even if the content is binary, not text (eg. PDF files are binary) and sent to the client using the response encoding and thereby modifing the binary content. You should rather use a different approach like this:

def file = new File(params.fileDir)    
response.setContentType("application/octet-stream")
response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")

response.outputStream << file.newInputStream() // Performing a binary stream copy
Siegfried Puchbauer
Nice one thanks. I was using the .text method but didn't know what it was actually doing - couldn't find any documentation on it :/
James Camfield
You can find the documentation inside the Groovy JDK (a documentation of the dynamic extensions to the Java SDK by Groovy). In this case it is the java.io.File.getText() method which is invoked: http://groovy.codehaus.org/groovy-jdk/java/io/File.html#getText()
Siegfried Puchbauer
A: 

I haven't had chance to test your solution, but while I'm here.

Should the MIME type "application/octet-stream" work for any file type? As the user can upload any file type, I don't want to have to try and work out which MIME type to use per file download, it seems more hassle than its worth!

Also, the fileName i'm setting in the header - if the name has a space the rest of the name is cut off.

e.g. "random file.txt" is uploaded.
on download, a file called "random" is asked to be saved.

Is there an easy way to resolve this, or should I just replace spaces with underscores or something?

Cheers

James Camfield
"application/octet-stream" is a good choice as a generic MIME type. The problem with the space in the filename is firefox only, right? You should avoid spaces here and replace them with an underscore or alike.
Siegfried Puchbauer
Thanks for the info. I've managed to get around the naming problem by simply surrounding the name with quotes in the header. This solved the problem in firefox, haven't actually tried IE yet.
James Camfield
A: 

..and return null from the action in order to stop page reload.