【问题标题】:Downloading BLOB file has no data下载 BLOB 文件没有数据
【发布时间】:2023-03-21 13:08:01
【问题描述】:

我正在尝试从 MySQL 下载 BLOB 数据,但我只能得到一个 1 KB 大小的文件。 我有一个包含复选框的表格,我正在寻找选中的复选框。这些值是 ID。 这是代码:

public class FileDownloadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        DBConnection DBC = new DBConnection();
        Connection con = DBC.connection();
        String[] checkBoxValues = request.getParameterValues("files");

        for (int i = 0; i < checkBoxValues.length; i++) {
            String fileDL = "select * from uploads where file_id='"+checkBoxValues[i]+"'";
            try {
                Statement st = con.createStatement();
                ResultSet rs = st.executeQuery(fileDL);
                while(rs.next()){
                    String fileName = rs.getString("file_name");
                    Blob blob = rs.getBlob("file");
                    InputStream input = blob.getBinaryStream();

                    int fileSize = (int) blob.length();
                    System.out.println(fileSize);

                    ServletContext context = getServletContext();
                    String mimeType = context.getMimeType(fileName);

                    if (mimeType == null) {        
                        mimeType = "application/octet-stream";
                    }

                    response.setContentType(mimeType);
                    response.setContentLength(fileSize);
                    String headerKey = "Content-Disposition";
                    String headerValue = String.format("attachment; filename=\"%s\"", fileName);
                    response.setHeader(headerKey, headerValue);

                    OutputStream output = response.getOutputStream();

                    byte[] buffer = new byte[4096];
                    int bytesRead = -1;

                    while ((bytesRead = input.read(buffer)) != -1) {
                        output.write(buffer, 0, bytesRead);
                    }
                    input.close();
                    output.close();         
                    }

            } catch (SQLException ex) {
                Logger.getLogger(FileDownloadServlet.class.getName()).log(Level.SEVERE, null, ex);
            }
        } 
    }
}

我不知道我哪里出错了。提前致谢!

【问题讨论】:

    标签: java mysql jsp servlets blob


    【解决方案1】:
    output.write(buffer, 0, bytesRead)
    

    始终使用相同的偏移量。你从来没有真正在你的结果流中前进。您必须将偏移量增加bytesRead

    编辑:解释

    您正在使用https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#write%28byte[],%20int,%20int%29 此方法将 buffer 中的字节写入输出流,从位置 0 开始。 现在,在下一次迭代中,您读取接下来的 4k 字节并再次将其写入输出流。但是您的偏移量没有改变,因此您 不附加 新的缓冲区内容,而是覆盖先前写入的字节,因为您说要再次从位置 0 写入。因此,您需要将偏移量提前您之前写入的相同字节数。

    编辑:剧透

    下面是剧透:

    int bytesRead = -1;
    int offset = 0;
    while ((bytesRead = input.read(buffer)) != -1) {
        output.write(buffer, offset, bytesRead);
        offset += bytesRead;
    }
    

    未测试。

    另外,为什么要写成 4k 块? 为什么不只是

    byte[] buffer = new byte[1];
    while (input.read(buffer) > 0) {
        output.write(buffer);
    }
    

    【讨论】:

    • 第一:你明白问题所在了吗?
    • 我不确定,你能解释一下吗?
    • 好的,添加说明。如果这还不清楚,请告诉我
    • 感谢您的解释,现在很清楚了。我根据您的建议更改了我的代码,但我仍然遇到了这个问题。也许我在上传时搞砸了?
    • 您能提供当前的代码吗?此外,计算您正在写入的字节数,以便验证您的期望。此外,尝试设置一个测试用例,在其中将结果写入文件系统以实际测试它,而不会产生整个 servlet 的开销。这样,您可以尝试缩小错误范围。 IE。编写一个简单的测试类,读取 blob 并将其写入 FS。
    猜你喜欢
    • 2012-03-13
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2016-09-02
    • 1970-01-01
    • 2019-09-15
    • 2015-08-22
    相关资源
    最近更新 更多