Spring MVC将上传的MultipartFile保存到特定文件夹

43

我希望在部署在Tomcat上的Spring 3 MVC应用程序中将上传的图像保存到特定文件夹中。

我的问题是,我无法将上传的图像文件保存到应用程序运行的主机上。

这是我尝试过的方法:

private void saveFile(MultipartFile multipartFile, int id) throws Exception {
    String destination = "/images/" + id + "/"  + multipartFile.getOriginalFilename();
    File file = new File(destination);
    multipartFile.transferTo(file);
}

结果: FileNotFoundException - 是的,我想创建这个文件!?!

我尝试使用context.getRealPathgetResources("destination"),但都没有成功。

如何在我的应用程序的特定文件夹中创建一个包含多部分文件内容的新文件?


当您尝试使用context.getRealPath或getResources(“destination”)时,您遇到了哪些错误?请参见https://dev59.com/Jk7Sa4cB1Zd3GeqP1jeg。 - Rob Kielty
啊,好的,谢谢。getRealPath 不起作用,因为如果应用程序部署到 war 文件中并未被解压缩,则返回 null!它在 war 容器外工作正常!但是有没有任何选项可以获取 war 内部文件的路径? - Alexander
我不这么认为。将文件添加到已部署的war包中并没有太多意义。这是你想要做的吗? - Rob Kielty
不是真的,但我读到有些Web服务器不会提取war文件,所以我认为为了使上述示例成为可能,必须有一种在war目录中编写的方法。因此,getRealPath不是正确的方法,因为它将返回null。 幸运的是,在我的tomcat上可以工作,但为了扩展我的视野,我想知道是否有另一种解决方案。 - Alexander
FileNotFoundException 表示您没有 /images/{id}/ 文件夹,您应该先创建文件夹。 - teik
6个回答

43

这段代码肯定会对你有所帮助。

String filePath = request.getServletContext().getRealPath("/"); 
multipartFile.transferTo(new File(filePath));

但是如果不使用http servlet请求,我们怎么能够获取路径呢? - Jijesh Kumar
有很多方法:您可以使用请求或会话来获取实际路径。谢谢Ravi。M - Phuong
@JijeshKumar 在控制器中发送HttpServletRequest类型的参数的最简单方法是什么? - Long tran

19

让我们在webapp中创建uploads目录,并将文件保存在webapp/uploads中:

@RestController
public class GreetingController {

    private final static Logger log = LoggerFactory.getLogger(GreetingController.class);

    @Autowired
    private HttpServletRequest request;


    @RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
        public
        @ResponseBody
        ResponseEntity handleFileUpload(@RequestParam("file") MultipartFile file) {
            if (!file.isEmpty()) {
                try {
                    String uploadsDir = "/uploads/";
                    String realPathtoUploads =  request.getServletContext().getRealPath(uploadsDir);
                    if(! new File(realPathtoUploads).exists())
                    {
                        new File(realPathtoUploads).mkdir();
                    }

                    log.info("realPathtoUploads = {}", realPathtoUploads);


                    String orgName = file.getOriginalFilename();
                    String filePath = realPathtoUploads + orgName;
                    File dest = new File(filePath);
                    file.transferTo(dest);

代码如下:
String realPathtoUploads = request.getServletContext().getRealPath(uploadsDir);

如果我从Idea IDE运行应用程序,则会返回以下路径:
C:\Users\Iuliia\IdeaProjects\ENumbersBackend\src\main\webapp\uploads\

如果我制作.war文件并在Tomcat下运行,则会返回以下路径:
D:\Programs_Files\apache-tomcat-8.0.27\webapps\enumbservice-0.2.0\uploads\

我的项目结构如下:
enter image description here


1
代码的最后一行 'file.transferTo(dest);' 报告了一个 IO 异常,错误信息是 "系统找不到指定的路径"。你有什么想法为什么会发生这种情况吗? - MR AND
1
@AND,你确定该路径在你的文件系统中存在吗?你需要先创建目录(手动或编程方式)。 - Yuliia Ashomok
1
这对我非常有帮助。虽然它与Ravi的答案实际上是相同的,但这是一个更详细的答案。 在Spring Boot 1.5.10中,此答案仍然有效。 - Stephan

13
您可以从MultipartFile获取inputStream,并将其复制到任何您想要的目录中。
public String write(MultipartFile file, String fileType) throws IOException {
    String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss-"));
    String fileName = date + file.getOriginalFilename();
    
    // folderPath here is /sismed/temp/exames
    String folderPath = SismedConstants.TEMP_DIR + fileType;
    String filePath = folderPath + File.separator + fileName;
    
    // Copies Spring's multipartfile inputStream to /sismed/temp/exames (absolute path)
    Files.copy(file.getInputStream(), Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
    return filePath;
}

这适用于Linux和Windows。


2
好的例子。只需用File.separator替换“/”。 - Simone Celia
但在 Mac 上无法运行。 - Hafiz Hamza

1

我看到了一个使用xml配置的Spring 3示例(请注意,这对于Spring 4.2.*不起作用):http://www.devmanuals.com/tutorials/java/spring/spring3/mvc/spring3-mvc-upload-file.html

<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000" />
<property name="uploadTempDir" ref="uploadDirResource" />
</bean>

<bean id="uploadDirResource" class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<value>C:/test111</value>
</constructor-arg>
</bean>


0

以下方法在Ubuntu上对我有效:

String filePath = request.getServletContext().getRealPath("/");
File f1 = new File(filePath+"/"+multipartFile.getOriginalFilename());
multipartFile.transferTo(f1);

0
String ApplicationPath = 
        ContextLoader.getCurrentWebApplicationContext().getServletContext().getRealPath("");

这是如何在Spring中获取应用程序的真实路径(不使用response,session等)


2
不应该使用 getRealPath() 来保存文件。请参考这个答案 - cozyconemotel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接