簡體   English   中英

從Java servlet下載文件為null

[英]Downloading file from Java servlet gives null

我正在嘗試創建一種方法,該方法允許用戶通過Servlet在文件系統上下載文件。 現在,正確的filename顯示在下載filename上,並且已下載文件,但文件內容始終為空。

我也嘗試過將文件內容打印到控制台,但是什么都沒有顯示。

有人可以在這里建議我做錯了什么嗎?

謝謝

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();

注釋

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

我建議進行幾次測試以找出問題所在,因為這里仍然有很多未知數。 我運行您的代碼沒有問題,因此它可能是您的servlet容器的配置問題,或者是關於文件系統的假設。

解決問題的關鍵是從基礎開始。 嘗試返回一個String而不是一個文件,以確保與服務器的通信實際上是正確的。 如果您得到相同的響應,則說明問題不在於文件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();

如果上述測試有效,則說明問題出在文件或用於讀取文件的方法上。 當前,您的代碼對所有與所請求文件完美匹配的條件進行了假設。 執行一些嚴格的測試以確保文件可訪問:

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);

最后根據讀取的字節數檢查文件系統報告的文件大小:

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

這些測試的結果應該可以為您縮小問題的范圍。

此解決方案是BalusC File Servlet博客的改進解決方案。

我使用此解決方案的原因是因為它在寫入數據之前將reset() HttpServletResponse response

@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();
            }
        }
    }
}

我希望這有幫助。

也許文件為空添加此行以確保文件不為空

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

只需添加outStream.setContentLength(inStream.available); 在outStream.write(bytes);之后

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM