vims liu
vims liu

Reputation: 643

jsp safari browser windows file download content disposition file name became -

below code is used for the download attachment encoding chinese character for file name.

w_inf_src = new File(p_filepath);
   w_inf = new FileInputStream(w_inf_src);
   p_response.setContentType(w_mime+";charset=UTF-8");
   p_response.setContentLength(new Long(w_inf_src.length()).intValue());
   p_response.setCharacterEncoding("UTF-8");
   p_request.setCharacterEncoding("UTF-8");

   p_response.setHeader("Content-disposition",
             "attachment;filename=\"" + (new java.net.URI(null, null, p_request, p_filename, null)).toASCIIString() + "\"");


   // Download File In Progress  
   w_outf = p_response.getOutputStream();
   w_bof = new BufferedOutputStream(w_outf);
   while ( (w_bytes_read = w_inf.read(w_buffer, 0, w_buffer.length)) != -1)
     w_bof.write(w_buffer, 0, w_bytes_read);      
   w_bof.flush();

I also tried the filename*=UTF-8''< encoded file name > but does not work

Upvotes: 1

Views: 1110

Answers (1)

Michele Mariotti
Michele Mariotti

Reputation: 7459

If you are using at least java 7 and Sevlet API 3.0, this is the way to go:

File w_inf_src = new File(p_filepath);
String encoding = StandardCharsets.UTF_8.name();
String w_disposition = String.format("%s;filename=\"%3$s\"; filename*=%2$s''%3$s",
    Part.ATTACHMENT,
    encoding,
    URLEncoder.encode(p_filename, encoding).replace("+", "%20"));

p_response.setContentType(w_mime);
p_response.setContentLengthLong(w_inf_src.length());
p_response.setCharacterEncoding(encoding);
p_response.setHeader("Content-Disposition", w_disposition);

byte[] w_buffer = new byte[p_response.getBufferSize()];
try(FileInputStream w_inf = new FileInputStream(w_inf_src);
    OutputStream w_outf = p_response.getOutputStream())
{
    int n;
    while((n = w_inf.read(w_buffer)) != -1)
    {
        w_outf.write(w_buffer, 0, n);
    }
}

Some notes:

  1. this is the most accurate disposition form you'll get, since it's urlencoded and space-sanitized.
  2. it's redundant to set the encoding in both content-type and content-encoding
  3. it's superfluous to set the request encoding: you are not reading.
  4. it's redundant to use a BufferedInputStream because the response has an internal buffering
  5. use your own buffer of the max available size (respose.getBufferSize())
  6. use try-with-resources where possible (if you are on Java 7+)
  7. if you are on Servlet API 3.0+ you have response.setContentLengthLong(), they finally understood that an integer is not enough
  8. alternatively use: response.setHeader("Content-Length", String.valueOf(w_inf_src.length()));: this ensures that large lengths are not cutted to int size

Upvotes: 1

Related Questions