使用 servlet 上传后图像文件已损坏 [重复]

Posted

技术标签:

【中文标题】使用 servlet 上传后图像文件已损坏 [重复]【英文标题】:Image file is corrupted after uploading using servlet [duplicate] 【发布时间】:2022-01-03 21:15:23 【问题描述】:

我正在尝试使用以下 servlet 上传图片 但是上传后我可以保存文件但我无法打开我检查了文件已损坏。

我没有使用注释,而是在 web.xml 中描述了 multipart-config。 在这段代码中,我试图获取使用 AJAX 发送数据的图像文件。 然后我被重定向到注册 servlet,我正在使用 InputStream 类来处理数据。 在此之后,我创建文件并将此 Inputdata 上传到服务器上某个目录中的文件。

public class Register extends HttpServlet
    @Override 
    protected void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        String email=req.getParameter("email");
        Part part = req.getPart("image");
        String filename = part.getSubmittedFileName();
        InputStream is = req.getInputStream();
        byte[] data = new byte[is.available()];
        String path = "D:\\FullstackWeb\\images\\icon\\"+filename;
        System.out.println(path);
        FileOutputStream fos=new FileOutputStream(path);
        fos.write(data);
        res.setContentType("text/html");
        PrintWriter out = res.getWriter();
        try 
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://dns1.nishchay.com:3306/register","demouser","123Nbr@");
            String query = "Insert INTO register.signup(username,email,userpassword,filename) values(? ,?, ?,?)";
            PreparedStatement pstmt= conn.prepareStatement(query);
            pstmt.setString(1, username);
            pstmt.setString(2, email);
            pstmt.setString(3, password);
            pstmt.setString(4, path);       
            pstmt.executeUpdate();      
            conn.close();
        catch(Exception e) 
            out.println("<h1>Issue is occured</h1>");       
               
    
```


【问题讨论】:

【参考方案1】:

你没有读入图像数据:

    InputStream is = req.getInputStream();
    byte[] data = new byte[is.available()];
    String path = "D:\\FullstackWeb\\images\\icon\\"+filename;
    System.out.println(path);
    FileOutputStream fos=new FileOutputStream(path);
    fos.write(data);

不包含任何is.read() 调用,也不会关闭FileOutputStream

此外,您分配的缓冲区对于大多数图像来说都很小。 InputStream.available() 状态的 JavaDoc

返回可以从该输入流中读取(或跳过)而不阻塞的字节数的估计值

要完全读取图像数据,您只需将上面的代码替换为

Files.copy(is, Paths.get("D:\\FullstackWeb\\images\\icon\\"+filename));

但有一个大警告:由于文件名是由您的服务用户提供的,这会使您的代码面临安全问题。

【讨论】:

感谢 Thomas 之前的解释。它适用于 Files.copy 方法。我刚开始学习servlet。请您帮我理解以下几点@因为文件名是由您的服务用户提供的,这会使您的代码面临安全问题。还有什么方法可以限制用户上传文件的大小? @nischit 关于大小限制见***.com/questions/28564683/… @nischit 关于可能的安全问题:part.getSubmittedFileName() 返回的内容完全取决于您的 servlet 用户发送的内容。恶意攻击者可以发送"..\\..\\index.html" 作为提交的文件名,你的代码会盲目地覆盖D:\FullstackWeb\index.html。有几件事情不适合这个狭小的空间。我建议您搜索“路径遍历”和“目录遍历”来了解问题。 感谢 Thomas 指出这个问题。

以上是关于使用 servlet 上传后图像文件已损坏 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用jsp和servlet将多个图像上传到文件夹[重复]

使用 AFNetworking 上传后图像不显示在浏览器上

使用retrofit2视频/图像损坏的AWS S3文件上传

在网站加载但未正确加载的图像(已损坏)

Servlet如何读取客户端上载的文件

带有 Android Retrofit V2 库的 AWS S3 Rest API,上传的图像已损坏