简体   繁体   中英

Downloading file from Java servlet gives null

I am trying to create a method that allows users to download a file on the file system via a Servlet. Right now, the correct filename shows on the download and a file is downloaded but the contents of the file are always null.

I've also tried to get the file contents to print to the console but nothing is showing up.

Can anyone suggest what I've done wrong here?

Thanks

String filePath = "uploads/" + request.getParameter( "filename" );
File downloadFile = new File( filePath );

String relativePath = getServletContext().getRealPath( "" );
System.out.println( "relativePath = " + relativePath );

ServletContext context = getServletContext();

String mimeType = context.getMimeType( filePath );
if( mimeType == null )
{
    mimeType = "application/octet-stream";
}
System.out.println( "MIME type: " + mimeType );

response.setContentType( mimeType );
response.setContentLength( (int) downloadFile.length() );

String headerKey = "Content-Disposition";
String headerValue = String.format( "attachment; filename=\"%s\"", downloadFile.getName() );
response.setHeader( headerKey, headerValue );
byte[] bytes = Files.readAllBytes( downloadFile.getAbsoluteFile().toPath() );
OutputStream outStream = response.getOutputStream();

System.out.println( bytes.toString() );

outStream.write( bytes );

outStream.flush();
outStream.close();

Annotations

@WebServlet(urlPatterns =
{ "/Routing/*" })
@MultipartConfig(location = "/tmp", fileSizeThreshold = 1024 * 1024,     maxFileSize = 1024 * 1024 * 5, maxRequestSize = 1024 * 1024 * 5 * 5)
public class Routing extends HttpServlet
{

I recommend several tests to isolate the problem since there are still too many unknowns here. I had no problems running your code, so it is likely a configuration issue with your servlet container, or an assumption about the filesystem.

The key to isolating the problem is start with the basics. Try to return a String instead of a file, to ensure that the communication with the server is actually behaving properly. If you get the same response, then you know the problem isn't with the file IO:

byte[] bytes = "This is a test.".getBytes();
int contentLength = bytes.length;
String mimeType = "text/plain";

response.setContentType( mimeType );
response.setContentLength( contentLength );
OutputStream outStream = response.getOutputStream();
outStream.write( bytes );
outStream.flush();
outStream.close();

If the above test worked, then you know the problem is with the file or the method you are using to read the file. You code currently makes a lot of assumptions about everything being perfect with the file that is being requested. Perform some rigorous testing to make certain the file is accessible:

int fileSize = downloadFile.length();
System.out.println("File path: " + downloadFile.getAbsolutePath());
System.out.println("exists: " + downloadFile.exists());
System.out.println("canRead: " + downloadFile.canRead());
System.out.println("File size: " + fileSize);

and finally check the file size reported by the filesystem against the number of bytes that were read:

byte[] bytes = Files.readAllBytes( downloadFile.getAbsoluteFile().toPath() );
int bytesRead = bytes.length;
System.out.println("bytes read: " + bytesRead);

The results of these tests should narrow down the problem for you.

This solution is a modified solution from BalusC File Servlet blog .

The reason I use this solution is because it reset() the HttpServletResponse response before writing data.

@WebServlet(urlPatterns =
{ "/Routing/*" })
@MultipartConfig(location = "/tmp", fileSizeThreshold = 1024 * 1024,     maxFileSize = 1024 * 1024 * 5, maxRequestSize = 1024 * 1024 * 5 * 5)
public class FileServlet extends HttpServlet {

    // Constants ----------------------------------------------------------------------------------

    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.


    // Actions ------------------------------------------------------------------------------------

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        // Get requested file by path info.
        String filePath = "uploads/" + request.getParameter( "filename" );

        // Check if file is actually supplied to the request URI.
        if (filePath == null) {
            // Do your thing if the file is not supplied to the request URI.
            // Throw an exception, or send 404, or show default/warning page, or just ignore it.
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
            return;
        }

        // Decode the file name (might contain spaces and on) and prepare file object.
        File downloadFile = new File( filePath );

        // Check if file actually exists in filesystem.
        if (!downloadFile.exists()) {
            // Do your thing if the file appears to be non-existing.
            // Throw an exception, or send 404, or show default/warning page, or just ignore it.
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
            return;
        }

        // Get content type by filename.
        String contentType = getServletContext().getMimeType(file.getName());

        // If content type is unknown, then set the default value.
        // For all content types, see: http://www.w3schools.com/media/media_mimeref.asp
        // To add new content types, add new mime-mapping entry in web.xml.
        if (contentType == null) {
            contentType = "application/octet-stream";
        }

        // Init servlet response.
        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setContentType(contentType);
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");

        // Prepare streams.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            // Open streams.
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            // Write file contents to response.
            byte[] bytes = Files.readAllBytes( downloadFile.getAbsoluteFile().toPath() );
            output.write(buffer, 0, bytes.length);
        } finally {
            // Gently close streams.
            close(output);
            close(input);
        }
    }

    // Helpers (can be refactored to public utility class) ----------------------------------------

    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                // Do your thing with the exception. Print it, log it or mail it.
                e.printStackTrace();
            }
        }
    }
}

I hope this helps.

也许文件为空添加此行以确保文件不为空

System.out.println("File size: " + bytes.length);

Just add outStream.setContentLength(inStream.available); after outStream.write( bytes );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM