Spring MVC ファイルをアップロードする


スポンサーリンク

Spring MVCで画像ファイルをアップロードするプログラムを書いてみました。

Apache上で動くHTMLから画像ファイルをポストして、それをサーバ側で受け取って、特定のディレクトリに格納します。

目次

ディレクトリ構成

ディレクトリ構成はこんな感じです。

f:id:sho322:20140720234229j:plain

pom.xml

STSで作ったSpring web mavenプロジェクトのデフォルトのpom.xmlに少し追加しています。
コメントに「追加したもの」と書いています。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework.samples.service.service</groupId>
  <artifactId>shiori</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
    <properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		
		<!-- Web -->
		<jsp.version>2.2</jsp.version>
		<jstl.version>1.2</jstl.version>
		<servlet.version>2.5</servlet.version>
		

		<!-- Spring -->
		<spring-framework.version>3.2.3.RELEASE</spring-framework.version>

		<!-- Hibernate / JPA -->
		<hibernate.version>4.2.1.Final</hibernate.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

		<!-- Test -->
		<junit.version>4.11</junit.version>

	</properties>
	
	<dependencies>
	
		<!-- Spring MVC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		
		<!-- Other Web dependencies -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>${jsp.version}</version>
			<scope>provided</scope>
		</dependency>
	
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		
		<!-- Test Artifacts -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring-framework.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		
		<!-- デフォルトから追加したもの -->
		<dependency>
	        <groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.0.0.GA</version>
		</dependency>

		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-validator</artifactId>
		    <version>4.3.1.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator-annotation-processor</artifactId>
			<version>4.1.0.Final</version>
		</dependency>
		
		<!-- Jackson JSON Mapper -->
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.10</version>
		</dependency>
		
	</dependencies>	
</project>

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">

    <display-name>shiori</display-name>
    
   <!--
		- Location of the XML file that defines the root application context.
		- Applied by ContextLoaderListener.
	-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/application-config.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    
    <!--
		- Servlet that dispatches request to registered handlers (Controller implementations).
	-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

ImageController.java

コントローラーは以下のとおりです。
ここでPOSTリクエストでアップロードされたファイルを受け取って、ディレクトリに格納しています。

デフォルトのままだと、Spring MVCのVIEWが開かれてしまうので、このリクエストを受けたらJSONを返すようにしました。

JacksonをMavenに書く必要があります。
これについて詳しくは、ページの一番下にリンクを貼ったサイトを見てください。

package shiori.controller;

import java.io.File;
import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import shiori.domain.Image;

@Controller
public class ImageController {
	
	@Autowired
	ServletContext context;
	
	@RequestMapping(value = "img_save", method=RequestMethod.POST)
	public @ResponseBody Image saveProduct(HttpServletRequest request,
					@RequestParam("file") MultipartFile file) throws IllegalStateException, IOException {

		Image image = new Image();
		
		
		if (file.getSize() > 0) {
			image.setName(file.getOriginalFilename());
			
			image.setSize(file.getSize());
			
			File imageFile = new File(context.getRealPath("/") + "/images",image.getName());
			if (!imageFile.exists()) {
				File imageDir = new File(context.getRealPath("/") + "/images");
				imageDir.mkdir();
			}
			file.transferTo(imageFile);
		}
		
		return image;
	}
}

Image.java

モデルの部分です。

package shiori.domain;

import java.io.Serializable;
import java.util.List;

import org.springframework.web.multipart.MultipartFile;

public class Image implements Serializable {

	private static final long serialVersionUID = 7302826202936253750L;
	
	private String name;
	
	private long size;
	
	private List<MultipartFile> images;
	
	private List<String> imageUrls;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<MultipartFile> getImages() {
		return images;
	}

	public void setImages(List<MultipartFile> images) {
		this.images = images;
	}

	public List<String> getImageUrls() {
		return imageUrls;
	}

	public void setImageUrls(List<String> imageUrls) {
		this.imageUrls = imageUrls;
	}

	public long getSize() {
		return size;
	}

	public void setSize(long size) {
		this.size = size;
	}
	
	
}

リクエストを投げるHTML

Apacheで動いているものです。
Spring MVCのViewでは無いですが、基本的には同じように使えます。

<!doctype html>
<html>
<head>
<meata charset="utf-8">
<title>file upload</title>
</head>
<body>
<form action="http://localhost:8080/shiori/img_save" method="post" enctype="multipart/form-data">
  <input type="file" name="file">
  <button type="submit">submit</button>
</form>
</body>
</html>

submitすると、JSONが返ってきます。

Spring MVCでレスポンスをJSONで返すのはこのサイトを参考にしました。
Spring MVCのレスポンスをJSONで返す


Spring MVC: A Tutorial

Spring MVC: A Tutorial