Java文件上传REST服务

时间:2020-02-23 14:37:08  来源:igfitidea点击:

在本教程中,我将解释如何构建javarestweb服务来通过HTTP从任何客户端上传文件。

将文件上传到web应用程序是当今的一项常见任务。很多服务都支持在他们的上上传图片或者文档。使用javaweb服务,这很容易实现。除了javaweb容器(由Tomcat、GlassFish或者JBoss等应用服务器提供)之外,我们还需要jersey框架来运行它。首先,将介绍如何实现web服务,然后给出两个使用该服务的客户机示例。

Java文件上传表单

建立文件上传REST服务

文件通过编码类型为“multipart/formdata”的httppost从客户机推送到我们的web服务。这样,除了文件之外,还可以向POST请求添加多个参数。让我们从需求开始。我们需要像Tomcat、GlassFish或者JBoss这样的web/应用服务器来部署服务。此外,我们将使用jersey框架来构建我们的服务端点。请注意,glassfish4.x版本需要jerseyversion2库,因此 如果我们使用glassfish4,请在POM文件中使用jersey 2.x依赖项

我将在这里发布整个POM文件,但是我们需要考虑的是jersey的依赖关系

<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>net.theitroad.tutorials</groupId>
	<artifactId>FileUploaderRESTService</artifactId>
	<version>1</version>
	<packaging>war</packaging>

	<name>File Uploader Rest Service</name>
	<url>https://theitroad.local</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-server</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-servlet</artifactId>
			<version>1.17.1</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey</groupId>
			<artifactId>jersey-json</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>com.sun.jersey.contribs</groupId>
			<artifactId>jersey-multipart</artifactId>
			<version>1.8</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<inherited>true</inherited>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
					<webResources>
						<resource>
							<!-- this is relative to the pom.xml directory -->
							<directory>${project.basedir}/src/main/resources
							</directory>
						</resource>
					</webResources>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

现在有了所有必要的库,让我们继续并实现REST服务。下面的代码中有几个地方我想提醒我们注意。首先注意@consumers的用法(MediaType.MULTIPART_FORM_数据)按请求的编码类型。其次,如果我们愿意,我们可能希望向该方法添加其他参数。例如,我们可能希望在上载时传递一些说明或者其他文本数据。最后,如果我们尝试将文件上载到不存在的目录中,Java将抛出异常。为了避免这个问题,我创建了createfolderrifnotexists(String dirName)方法。

package net.theitroad.tutorials.services;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;

/**
 * This example shows how to build Java REST web-service to upload files
 * accepting POST requests with encoding type "multipart/form-data". For more
 * details please read the full tutorial on
 * https://theitroad.local/java-file-upload-rest-service
 * 
 * @author theitroad.local
 */
@Path("/upload")
public class FileUploadService {

	/** The path to the folder where we want to store the uploaded files */
	private static final String UPLOAD_FOLDER = "c:/uploadedFiles/";

	public FileUploadService() {
	}

	@Context
	private UriInfo context;

	/**
	 * Returns text response to caller containing uploaded file location
	 * 
	 * @return error response in case of missing parameters an internal
	 *         exception or success response if file has been stored
	 *         successfully
	 */
	@POST
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response uploadFile(
			@FormDataParam("file") InputStream uploadedInputStream,
			@FormDataParam("file") FormDataContentDisposition fileDetail) {

		//check if all form parameters are provided
		if (uploadedInputStream == null || fileDetail == null)
			return Response.status(400).entity("Invalid form data").build();

		//create our destination folder, if it not exists
		try {
			createFolderIfNotExists(UPLOAD_FOLDER);
		} catch (SecurityException se) {
			return Response.status(500)
					.entity("Can not create destination folder on server")
					.build();
		}

		String uploadedFileLocation = UPLOAD_FOLDER + fileDetail.getFileName();
		try {
			saveToFile(uploadedInputStream, uploadedFileLocation);
		} catch (IOException e) {
			return Response.status(500).entity("Can not save file").build();
		}

		return Response.status(200)
				.entity("File saved to " + uploadedFileLocation).build();
	}

	/**
	 * Utility method to save InputStream data to target location/file
	 * 
	 * @param inStream
	 *            - InputStream to be saved
	 * @param target
	 *            - full path to destination file
	 */
	private void saveToFile(InputStream inStream, String target)
			throws IOException {
		OutputStream out = null;
		int read = 0;
		byte[] bytes = new byte[1024];

		out = new FileOutputStream(new File(target));
		while ((read = inStream.read(bytes)) != -1) {
			out.write(bytes, 0, read);
		}
		out.flush();
		out.close();
	}

	/**
	 * Creates a folder to desired location if it not already exists
	 * 
	 * @param dirName
	 *            - full path to the folder
	 * @throws SecurityException
	 *             - in case you don't have permission to create the folder
	 */
	private void createFolderIfNotExists(String dirName)
			throws SecurityException {
		File theDir = new File(dirName);
		if (!theDir.exists()) {
			theDir.mkdir();
		}
	}

}

最后,我们需要配置web.xml文件将我们的类注册为web服务并使其在启动时运行。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	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>net.theitroad.tutorials.services</display-name>
	<servlet>
		<servlet-name>Jersey REST Service</servlet-name>
		<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
		<init-param>
			<param-name>com.sun.jersey.config.property.packages</param-name>
			<param-value>net.theitroad.tutorials.services</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Jersey REST Service</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>
</web-app>

就这样!现在我们可以构建和部署WAR文件了。如果我们使用与上面代码中提供的名称完全相同的名称,那么服务URL(假设我们在localhost上运行)将是:http://localhost:8080/FileUploaderRESTService-1/rest/上传

文件上传HTML表单

我们可以使用一个非常简单HTML post表单作为客户端将文件发送到服务器。

请注意使用“multipart/form data”作为编码类型。我们还需要添加名为“file”的file类型的<input>

Choose file to upload<br>
<form action="http://localhost:8080/FileUploaderRESTService-1/rest/upload" method="post" enctype="multipart/form-data">
	<input name="file" id="filename" type="file" <br>
	<button name="submit" type="submit">Upload</button>
</form>

正如我已经提到的,你可以在你的请求中添加另外的数据。在这种情况下,不要忘记在web服务中处理它