springboot内置tomcat在tmp的临时文件被系统删除导致上传错误

springboot内置tomcat在tmp的临时文件被系统删除导致上传错误,第1张

正常运行的springboot项目,突然出现文件上传异常

java.io.IOException: The temporary upload location [/tmp/tomcat.7278393013633127856.2220/work/Tomcat/localhost/ROOT] is not valid

因为上传的文件会缓存到本地磁盘,而缓存的路径就是上面的 /tmp/tomcat.7278393013633127856.2220/work/Tomcat/localhost/ROOT ,而错误提示明显显示文件不存在,排查后发现是Linux系统自动删除了tmp目录下的文件

重启应用,该方法只能临时解决问题。

增加服务配置,自定义baseDir。

配置不删除tmp目录下的tomcat

是通过数据流上传吗? 利用 B\S架构还是 C\S架构?

jsp文件上传大多采用采用开源项目来简化处理,这里列出常用的两个jar包的实现,并进行比较,说明他们的优缺点和应该注意的问题。

Commons FileUpload,可以在http://jakarta.apache.org/commons/fileupload/下载,这个包需要Commons IO的支持,可以在http://jakarta.apache.org/commons/io/下载

com.oreilly.servlet,可以在http://www.servlets.com/cos/下载

Commons FileUpload提供三种文件上传处理方式,DiskFileUpload、ServletFileUpload和PortletFileUpload三种方式,其中DiskFileUpload已经在javadoc下已经被标记为过期的方法,建议用ServletFileUpload代替,而PortletFileUpload需要配合portlet-api来使用,所以这里我们只介绍ServletFileUpload,并且这个也是最常用的。

com.oreilly.servlet也提供了三种文件上传的处理方式,MultipartWrapper、MultipartRequest和MultipartParser三种方式,其中MultipartWrapper和MultipartRequest的用法基本相同,并且没有MultipartRequest提供的 *** 作多,所以这里介绍MultipartRequest,MultipartParser和前两者有些不同,可以用来处理某些特殊情况,例如表单中有两个同名的文件上传选择框。

我们暂时称三面三种文件上传方式分别为:ServletFileUpload方式(MultipartTestServlet)、MultipartRequest方式(MultipartTestServlet2)、MultipartParser方式(MultipartTestServlet3)

代码如下:

test.html

<%@ page language="java" import="java.util.*" contentType="text/htmlcharset=gbk" pageEncoding="gbk"%>

<html>

<body>

<form action="MultipartTestServlet" enctype="multipart/form-data" method="post">

<input type="text" name="username" /><br />

<input type="file" name="myfile" /><br/>

<input type="file" name="myfile" /><br/>

<input type="submit" />

</form>

<br/><br/><br/><br/>

<form action="MultipartTestServlet2" enctype="multipart/form-data" method="post">

<input type="text" name="username" /><br />

<input type="file" name="myfile" /><br/>

<input type="file" name="myfile" /><br/>

<input type="submit" />

</form>

<br/><br/><br/><br/>

<form action="MultipartTestServlet3" enctype="multipart/form-data" method="post">

<input type="text" name="username" /><br />

<input type="file" name="myfile" /><br/>

<input type="file" name="myfile" /><br/>

<input type="submit" />

</form>

</body>

</html>

MultipartTestServlet.java

package com.bug.servlet

import java.io.File

import java.io.IOException

import java.util.ArrayList

import java.util.Iterator

import java.util.List

import javax.servlet.ServletException

import javax.servlet.http.HttpServlet

import javax.servlet.http.HttpServletRequest

import javax.servlet.http.HttpServletResponse

import org.apache.commons.fileupload.FileItem

import org.apache.commons.fileupload.FileUpload

import org.apache.commons.fileupload.FileUploadException

import org.apache.commons.fileupload.RequestContext

import org.apache.commons.fileupload.disk.DiskFileItemFactory

import org.apache.commons.fileupload.servlet.ServletFileUpload

import org.apache.commons.fileupload.servlet.ServletRequestContext

public class MultipartTestServlet extends HttpServlet {

public MultipartTestServlet() {

super()

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

request.setCharacterEncoding("gbk")

RequestContext requestContext = new ServletRequestContext(request)

if(FileUpload.isMultipartContent(requestContext)){

DiskFileItemFactory factory = new DiskFileItemFactory()

factory.setRepository(new File("c:/tmp/"))

ServletFileUpload upload = new ServletFileUpload(factory)

//upload.setHeaderEncoding("gbk")

upload.setSizeMax(2000000)

List items = new ArrayList()

try {

items = upload.parseRequest(request)

} catch (FileUploadException e1) {

System.out.println("文件上传发生错误" + e1.getMessage())

}

Iterator it = items.iterator()

while(it.hasNext()){

FileItem fileItem = (FileItem) it.next()

if(fileItem.isFormField()){

System.out.println(fileItem.getFieldName() + " " + fileItem.getName() + " " + new String(fileItem.getString().getBytes("iso8859-1"), "gbk"))

}else{

System.out.println(fileItem.getFieldName() + " " +

fileItem.getName() + " " +

fileItem.isInMemory() + "" +

fileItem.getContentType() + " " +

fileItem.getSize())

if(fileItem.getName()!=null &&fileItem.getSize()!=0){

File fullFile = new File(fileItem.getName())

File newFile = new File("c:/temp/" + fullFile.getName())

try {

fileItem.write(newFile)

} catch (Exception e) {

e.printStackTrace()

}

}else{

System.out.println("文件没有选择 或 文件内容为空")

}

}

}

}

}

}

MultipartTestServlet2.java

package com.bug.servlet

import java.io.IOException

import java.util.Enumeration

import javax.servlet.ServletException

import javax.servlet.http.HttpServlet

import javax.servlet.http.HttpServletRequest

import javax.servlet.http.HttpServletResponse

import com.oreilly.servlet.MultipartRequest

import com.oreilly.servlet.multipart.DefaultFileRenamePolicy

public class MultipartTestServlet2 extends HttpServlet {

public MultipartTestServlet2() {

super()

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//request.setCharacterEncoding("gbk") 不起作用

System.out.println("start ")

MultipartRequest multi = new MultipartRequest(request, "c:/tmp/", 2*1024*1024, "gbk", new DefaultFileRenamePolicy())

System.out.println("start ")

Enumeration filesName = multi.getFileNames()

Enumeration paramsName = multi.getParameterNames()

while(paramsName.hasMoreElements()){

String paramName = (String) paramsName.nextElement()

System.out.println(multi.getParameter(paramName))

}

while(filesName.hasMoreElements()){

String fileName = (String) filesName.nextElement()

System.out.println(multi.getFilesystemName(fileName) + " " +

multi.getOriginalFileName(fileName) + " " +

multi.getContentType(fileName) + " ")

if(multi.getFilesystemName(fileName)!=null &&!multi.getFilesystemName(fileName).equals(""))

System.out.println(multi.getFile(fileName).toURI())

}

}

}

MultipartTestServlet3.java

package com.bug.servlet

import java.io.File

import java.io.IOException

import javax.servlet.ServletException

import javax.servlet.http.HttpServlet

import javax.servlet.http.HttpServletRequest

import javax.servlet.http.HttpServletResponse

import com.oreilly.servlet.multipart.FilePart

import com.oreilly.servlet.multipart.MultipartParser

import com.oreilly.servlet.multipart.ParamPart

import com.oreilly.servlet.multipart.Part

public class MultipartTestServlet3 extends HttpServlet {

public MultipartTestServlet3() {

super()

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

MultipartParser mp = new MultipartParser(request, 2*1024*1024, false, false, "gbk")

Part part

while ((part = mp.readNextPart()) != null) {

String name = part.getName()

if (part.isParam()) {

ParamPart paramPart = (ParamPart) part

String value = paramPart.getStringValue()

System.out.println("param: name=" + name + "value=" + value)

}

else if (part.isFile()) {

// it's a file part

FilePart filePart = (FilePart) part

String fileName = filePart.getFileName()

if (fileName != null) {

long size = filePart.writeTo(new File("c:/tmp/"))

System.out.println("file: name=" + name + "fileName=" + fileName +

", filePath=" + filePart.getFilePath() +

", contentType=" + filePart.getContentType() +

", size=" + size)

}

else {

System.out.println("file: name=" + name + "EMPTY")

}

System.out.flush()

}

}

}

}

web.xml中加入

<servlet>

<servlet-name>MultipartTestServlet</servlet-name>

<servlet-class>com.bug.servlet.MultipartTestServlet</servlet-class>

</servlet>

<servlet>

<servlet-name>MultipartTestServlet2</servlet-name>

<servlet-class>com.bug.servlet.MultipartTestServlet2</servlet-class>

</servlet>

<servlet>

<servlet-name>MultipartTestServlet3</servlet-name>

<servlet-class>com.bug.servlet.MultipartTestServlet3</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>MultipartTestServlet</servlet-name>

<url-pattern>/MultipartTestServlet</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>MultipartTestServlet2</servlet-name>

<url-pattern>/MultipartTestServlet2</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>MultipartTestServlet3</servlet-name>

<url-pattern>/MultipartTestServlet3</url-pattern>

</servlet-mapping>

问题1、中文问题:

三种凡是都可以通过自己的方法来设置encoding为gbk开处理和解决中文问题,包括初始化的时候传入gbk作为参数,或是是初始化后通过setEncoding的方式来实现。

另外ServletFileUpload方式也可以通过request.setCharacterEncoding("gbk")的方式来实现,而其它两种方式不支持这种方式。

问题2、文件大小限制

ServletFileUpload方式可以设置文件大小限制,也可以不用设置,例子中的upload.setSizeMax(2000000)就可以注释掉。如果设置upload.setSizeMax(-1),表明不限制上传的大小。文档中没有指明默认的限制的多少,我在不设置的情况下上传了一个9M的东西,可以上传,估计默认是不限制大小的。

而MultipartRequest方式和MultipartParser方式是必须设置文件的上传文件的大小限制的,如果不设置,默认是1M的大小限制。

问题3、文件上传发生错误

如果文件上传过程中发生任何错误,或者是文件的大小超出了范围,系统都将抛出错误。

ServletFileUpload方式在upload.parseRequest(request)时抛出错误

MultipartRequest方式在new MultipartRequest(。。。)时抛出错误

MultipartParser方式在new MultipartParser(。。。)时抛出错误

问题4、上传同名文件时,他们保存到临时目录是的冲突问题

ServletFileUpload方式,不会有冲突,系统会把上传得文件按照一定的规则重新命名,保证不会冲突

MultipartParser方式,会产生冲突,系统会把文件按照上传时的文件名,保存到临时目录下,如果两个用会同时上传文件名相同的文件,那么就可能会产生冲突,一方把另一方的临时文件给替换了。

MultipartRequest方式,在初始化时如果提供了一个名称转换策略,就不会有冲突,如果不提桶,就会有冲突。在上面的例子中我们提供了一个new DefaultFileRenamePolicy()保证了文件名不会有冲突发生。

问题5:表单中有两个同名的文件上传选择框,就像我们例子中的myfile一样,每个表单中有两个name=“myfile”的上传框

ServletFileUpload方式,可以处理,可以分别得到他们各自的文件,

MultipartRequest方式,不可以处理,会发生冲突,会有一个上传框的文件覆盖了另外一个。

MultipartParser方式,可以处理,可以分别得到他们各自的文件,

备注:

代码比较乱,主要是为了说明他们间的区别。他们的详细地使用说明还是要参考他的javadoc和domo。

package com.quantongfu.ftp.ftp

import java.io.File

import java.io.FileInputStream

import java.io.IOException

import java.net.ServerSocket

import java.util.List

import org.apache.commons.net.ftp.FTPReply

import org.apache.log4j.Logger

import org.apache.log4j.net.SocketServer

import com.quantongfu.conf.FtpConf

/**

 * @项目名称: telinSyslog

 * @文件名称: Ftp.java

 * @创建日期:2015年9月14日 下午3:22:08

 * @功能描述:ftp实体类,用于连接,上传

 * @修订记录:

 */

public class Ftp {

    private static Logger logger = Logger.getLogger(Ftp.class)

    private FTPClient ftp

    /**

     * 

     * @param path

     *            上传到ftp服务器哪个路径下

     * @param addr

     *            地址

     * @param port

     *            端口号

     * @param username

     *            用户名

     * @param password

     *            密码

     * @return

     * @throws Exception

     */

    public boolean connect() throws Exception {

        boolean result = false

        ftp = new FTPClient()

        int reply

        ftp.connect(FtpConf.FTP_HOST, FtpConf.FTP_PORT)

        ftp.login(FtpConf.FTP_USER_NAME, FtpConf.FTP_PASSWORD)

        ftp.setFileType(FTPClient.BINARY_FILE_TYPE)

        ftp.setDataTimeout(60000)

        reply = ftp.getReplyCode()

        if (!FTPReply.isPositiveCompletion(reply)) {

            ftp.disconnect()

            return result

        }

        if (FtpConf.IS_FTP_DIRECTORY) {

            ftp.changeWorkingDirectory(FtpConf.FTP_DIRECTORY)

        }

        result = true

        return result

    }

    /**

     * 

     * @param files

     *            上传的文件

     * @throws Exception

     */

    public boolean upload(File file) throws IOException {

        FileInputStream input = null

        try {

            input = new FileInputStream(file)

            boolean b = ftp.storeFile(file.getName() + ".tmp", input)

            if (b) {

                b = ftp.rename(file.getName() + ".tmp", file.getName())

            }

            return b

        } catch (Exception e) {

            e.printStackTrace()

            return false

        } finally {

            if (input != null) {

                input.close()

            }

        }

    }

    /**

     * 

     * @param files

     *            上传的文件

     * @throws Exception

     */

    public boolean upload(ServerSocket server, File file) throws Exception {

        FileInputStream input = null

        try {

            if (!file.exists()) {

                return true

            }

            input = new FileInputStream(file)

            boolean b = ftp.storeFile(server, file.getName() + ".tmp", input)

            if (b) {

                b = ftp.rename(file.getName() + ".tmp", file.getName())

                if (b) {

                    file.delete()

                }

            }

            return b

        } catch (Exception e) {

            logger.error("ftp error" + e.getMessage())

            return false

        } finally {

            if (input != null) {

                try {

                    input.close()

                } catch (IOException e) {

                    e.printStackTrace()

                }

            }

        }

    }

        /*断开连接*/

    public void disConnect() {

        try {

            if (ftp != null) {

                ftp.disconnect()

            }

        } catch (IOException e) {

            e.printStackTrace()

        }

    }

        /*获取连接*/

    public static Ftp getFtp() {

        Ftp ftp = new Ftp()

        try {

            ftp.connect()

        } catch (Exception e) {

            logger.error("FTP连接异常" + e.getMessage())

            e.printStackTrace()

        }

        return ftp

    }

        /*重连*/

    public Ftp reconnect() {

        disConnect()

        return getFtp()

    }

}

使用Apache FtpClient jar包,获取jar : http://commons.apache.org/net/


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/tougao/11859521.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-19
下一篇2023-05-19

发表评论

登录后才能评论

评论列表(0条)

    保存