使用REST服务上载和下载文件

x33g5p2x  于2022-10-15 转载在 其他  
字(16.6k)|赞(0)|评价(0)|浏览(921)

rest服务教程是使用rest服务处理文件上传和下载的快速指南。我们将通过rest服务示例演示如何使用具有不同前端(AngularJS和JSP)的JAX-RS API上传和下载文件。最重要的是,我们将展示如何构建JUnit测试来测试使用RESTEasy客户端API上传的文件。

使用REST服务上载和下载文件

为了管理文件上载和下载,我们将使用核心JAX-RS API和Rest Easy实现,以及Apache Commons IO库中的IOUtil类。以下是我们Rest端点的源代码:

package com.mastertheboss.rest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;

@Path("/file")
public class RestFilesDemo {

	@Context
	private ServletContext context;

	@POST
	@Path("/upload")
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response uploadFile(MultipartFormDataInput input) throws IOException {

		Map<String, List<InputPart>> uploadForm = input.getFormDataMap();

		// Get file data to save
		List<InputPart> inputParts = uploadForm.get("attachment");

		for (InputPart inputPart : inputParts) {
			try {

				MultivaluedMap<String, String> header = inputPart.getHeaders();
				String fileName = getFileName(header);

				// convert the uploaded file to inputstream
				InputStream inputStream = inputPart.getBody(InputStream.class, null);

				byte[] bytes = IOUtils.toByteArray(inputStream);

				//String path = System.getProperty("user.home") + File.separator + "uploads";
				File customDir = new File(Config.UPLOAD_FOLDER);

				if (!customDir.exists()) {
					customDir.mkdir();
				}
				fileName = customDir.getCanonicalPath() + File.separator + fileName;
				writeFile(bytes, fileName);

				return Response.status(200).entity("Uploaded file name : " + fileName+" . <br/> <a href='"+context.getContextPath()+"'>Back</a>").build();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	@POST
	@Path("/download")
	@Produces(MediaType.APPLICATION_OCTET_STREAM)
	@Consumes("application/x-www-form-urlencoded")
	public Response downloadFileWithPost(@FormParam("file") String file) {

		String path = System.getProperty("user.home") + File.separator + "uploads";
		File fileDownload = new File(path + File.separator + file);
		ResponseBuilder response = Response.ok((Object) fileDownload);
		response.header("Content-Disposition", "attachment;filename=" + file);
		return response.build();
	}

	@GET
	@Path("/download")
	@Produces(MediaType.APPLICATION_OCTET_STREAM)
	public Response downloadFileWithGet(@QueryParam("file") String file) {
		System.out.println("Download file "+file);
		File fileDownload = new File(Config.UPLOAD_FOLDER + File.separator + file);
		ResponseBuilder response = Response.ok((Object) fileDownload);
		response.header("Content-Disposition", "attachment;filename=" + file);
		return response.build();
	}

	@GET
	@Path("/list")
	@Produces(MediaType.APPLICATION_JSON)
	public List<String> listFiles() {

		List<String> listFiles = new ArrayList<>();
		File fileFolder = new File(Config.UPLOAD_FOLDER);
		File[] list = fileFolder.listFiles();

		for (File f: list) {
			if (!f.isDirectory()) {
				listFiles.add(f.getName());
			}
		}
		return listFiles;
	}

	private String getFileName(MultivaluedMap<String, String> header) {

		String[] contentDisposition = header.getFirst("Content-Disposition").split(";");

		for (String filename : contentDisposition) {
			if ((filename.trim().startsWith("filename"))) {
				String[] name = filename.split("=");
				String finalFileName = name[1].trim().replaceAll("\"", "");
				return finalFileName;
			}
		}
		return "unknown";
	}
	// Utility method
	private void writeFile(byte[] content, String filename) throws IOException {
		File file = new File(filename);

		if (!file.exists()) {
			file.createNewFile();
		}
		FileOutputStream fop = new FileOutputStream(file);
		fop.write(content);
		fop.flush();
		fop.close();
	}
}

以下是所用方法的一些详细信息:

*listFiles:此方法返回Config.UPLOAD_FOLDER中可用的文件列表
*uploadFile(MultipartFormDataInput输入):此方法上载File,使用HTTP POST方法中的MULTIPART_FORM_DATA
*downloadFileWithPost(@FormParam(“file”)String文件):此方法从HTTP POST下载文件,生成二进制流,并将文件名作为Form参数传递
*downloadFileWithGet(@QueryParam(“file”)String file):此方法还下载file,但它包含filename作为Query参数

接下来,为了确保“uploads”文件夹存在,以下Context Listener将在部署应用程序后创建该文件夹:

package com.mastertheboss.rest;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.File;

@WebListener
public class WebContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        if (!new File(Config.UPLOAD_FOLDER).exists()) {
            new File(Config.UPLOAD_FOLDER).mkdir();
        }

    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //. . .
    }
}

为Rest Service示例的前端编码

有几种方法可以休息我们的rest上传服务。这里我们将展示一个REST客户端集合,它可以将文件作为多部分表单数据发送。

使用Postman上载文件

如果您正在使用Postman测试您的REST服务,您所需要做的就是创建一个New|HTTP请求t。
从HTTP请求用户界面:
1.输入REST服务的URL(例如。http://localhost:8080/rest-文件管理器/resr/file/upload)
1.选择POST作为方法
1.在Body中选择表单数据
1.输入类型文件的键“附件”。上载“值”列中的文件
例如:


小时
最后,单击发送从Postman上传文件。

使用AngularJS上载文件

首先,创建以下索引。使用AngularJS控制器与我们的REST服务交互的jsp页面:

<html>
<head>
 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
 <link rel="stylesheet" type="text/css" href="stylesheet.css" media="screen" />

<script type = "text/javascript">
	angular.module('app', [])
	.controller('ctrl', function ($scope, $http) {
		$scope.files = [];

		$scope.loadData = function () {
			$http({
				method: 'GET',
				url: '/rest-file-manager/rest/file/list'
			}).then(function successCallback(response) {
				$scope.files = response.data;
			}, function errorCallback(response) {
				console.log(response.statusText);
			});
		}

		$scope.downloadFile = function (filename) {

			$http({
				method: 'GET',
				url: '/rest-file-manager/rest/file/download',
				params: {
					file: filename
				},
				responseType: 'arraybuffer'

			}).success(function (data, status, headers) {

				headers = headers();

				var contentType = headers['content-type'];
				var linkElement = document.createElement('a');

				try {

					var blob = new Blob([data], {
						type: contentType
					});

					var url = window.URL.createObjectURL(blob);

					linkElement.setAttribute('href', url);
					linkElement.setAttribute("download", filename);

					var clickEvent = new MouseEvent("click", {

						"view": window,
						"bubbles": true,
						"cancelable": false

					});

					linkElement.dispatchEvent(clickEvent);

				} catch (ex) {
					console.log(ex);
				}

			}).error(function (data) {
				console.log(data);
			});

		};

		//call loadData when controller initialized
		$scope.loadData();
	})
</script>

<title>REST Download demo with AngularJS</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body ng-app='app' ng-controller='ctrl'>
    <h1>REST Upload/Download demo using AngularJS</h2>
	<h2>Upload file</h2>
	<form method="post" action="rest/file/upload"
		enctype="multipart/form-data">
		<input type="hidden" name="action" value="upload" /> <label>Load
			your file:</label> <input type="file" name="attachment" /> <br /> <input
			type="submit" value="Upload file" />
	</form>

	<h2>Download file</h2>

        <div class="divTable blueTable">
                <div class="divTableHeading">
                    <div  class="divTableHead">File Name</div>
                    <div  class="divTableHead">Action</div>
                </div>
                <div class="divTableRow" ng-repeat="file in files">
                    <div class="divTableCell">{{ file }}</div>
                    <div class="divTableCell"><a ng-click="downloadFile( file )" class="myButton">Download</a> </div>
                </div>
            </div>
</body>
</html>

接下来,使用以下方法部署示例应用程序:

mvn clean install wildfly:deploy

最后,下面是我们在上传示例XML文件后Rest Endpoint的工作方式:


小时

一个简单的JSP/HTML文件管理器

为了上传和下载文件,您还可以使用一种最简单的方法:一个包含JSP代码的HTML页面。JSP部分主要用于显示服务器上可用的文件列表:

<%@page import="java.io.*, com.mastertheboss.rest.Config" %>
        <%@page import="java.util.*" %> 
        <%!        public void GetDirectory(String a_Path, Vector a_files, Vector a_folders) {
                File l_Directory = new File(a_Path);
                File[] l_files = l_Directory.listFiles();

                for (int c = 0; c < l_files.length; c++) {
                    if (l_files[c].isDirectory()) {
                        a_folders.add(l_files[c].getName());
                    } else {
                        a_files.add(l_files[c].getName());
                    }
                }


            }
        %> 


<html>
<head>
<title>Start Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
	<h2>REST Upload demo</h2>
	<form method="post" action="rest/file/upload"
		enctype="multipart/form-data">
		<input type="hidden" name="action" value="upload" /> <label>Load
			your file:</label> <input type="file" name="attachment" /> <br /> <input
			type="submit" value="Upload file" />
	</form>

	<h2>REST Download demo</h2>
	<form method="POST" action="rest/file/download">
		File name: <input type="text" name="file"> 
		<input type="submit">


	</form>
	
	<h2>Current Directory $HOME/uploads:</h2>
	<br/>
	        <%
            Vector l_Files = new Vector(), l_Folders = new Vector();
            GetDirectory(Config.UPLOAD_FOLDER, l_Files, l_Folders);
            out.println("<ul>");   
            for (int a = 0; a < l_Files.size(); a++) {
                out.println("<li>" + l_Files.elementAt(a).toString() + "</li>");
            }
            out.println("</ul>");
           
        %> 
</body>
</html>

下面是我们正在使用的简单JSP前端:


小时

添加JUnit Test类以测试REST上载

最后,我们在本教程中包括一个JUnit Test类示例,它显示了其中最难的部分:使用REST Easy Client API管理多部件请求以上载文件:

package com.mastertheboss.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.junit.Test;

public class TestRest {

    String FILENAME="test-file.txt";
    @Test
    public void sendFile() throws Exception {
         
        Client client = ClientBuilder.newClient();

    	WebTarget target = client.target("http://localhost:8080/rest-file-manager/rest/file/upload");
    	
    	MultipartFormDataOutput mdo = new MultipartFormDataOutput();

    	createFile();

    	File filePath = new File(FILENAME);
    	
    	// Check that file exists

    	assertTrue(filePath.exists());
    	
    	mdo.addFormData("attachment", new FileInputStream(filePath),
    		    MediaType.APPLICATION_OCTET_STREAM_TYPE,filePath.getName());
    	
    	GenericEntity<MultipartFormDataOutput> entity = new GenericEntity<MultipartFormDataOutput>(mdo) {};
    	
    	Response r = target.request().post( Entity.entity(entity, MediaType.MULTIPART_FORM_DATA_TYPE));
    	
    	// Check that upload was successful
    	assertEquals(r.getStatus(), 200);
    	
    	 
}

    private void createFile() {
        try {
            PrintWriter writer = new PrintWriter(FILENAME, "UTF-8");
            writer.println("Some text");
            writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

}


这是pom。用于构建和部署项目的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<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>com.mastertheboss</groupId>
	<artifactId>rest-file-manager</artifactId>
	<version>1.1</version>
	<packaging>war</packaging>

	<name>rest-file-manager</name>

	<properties>
		<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<version.server.bom>19.0.0.Final</version.server.bom>

	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.wildfly.bom</groupId>
				<artifactId>wildfly-jakartaee8-with-tools</artifactId>
				<version>${version.server.bom}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>

		<dependency>
			<groupId>org.jboss.spec.javax.servlet</groupId>
			<artifactId>jboss-servlet-api_4.0_spec</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.6</version>
		</dependency>

		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-multipart-provider</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.spec.javax.ws.rs</groupId>
			<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
			<scope>provided</scope>
		</dependency>


		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-client</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>

		<finalName>rest-file-manager</finalName>
		<plugins>
			<plugin>
				<groupId>org.wildfly.plugins</groupId>
				<artifactId>wildfly-maven-plugin</artifactId>
				<version>2.0.0.Final</version>
				<configuration>
					<filename>${project.build.finalName}.war</filename>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<compilerArguments>
						<endorseddirs>${endorsed.dir}</endorseddirs>
					</compilerArguments>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.6</version>
				<executions>
					<execution>
						<phase>validate</phase>
						<goals>
							<goal>copy</goal>
						</goals>
						<configuration>
							<outputDirectory>${endorsed.dir}</outputDirectory>
							<silent>true</silent>
							<artifactItems>
								<artifactItem>
									<groupId>javax</groupId>
									<artifactId>javaee-endorsed-api</artifactId>
									<version>7.0</version>
									<type>jar</type>
								</artifactItem>
							</artifactItems>
						</configuration>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
			</plugin>
		</plugins>

	</build>
	<profiles>
		<profile>
			<id>install</id>
			<activation>
				<activeByDefault>true</activeByDefault>
			</activation>
			<properties>
				<maven.test.skip>true</maven.test.skip>
			</properties>
		</profile>
		<profile>
			<id>test</id>
			<properties>
				<maven.test.skip>false</maven.test.skip>
			</properties>
		</profile>
	</profiles>
</project>

要运行测试,请使用“测试”配置文件,如下所示:

$ mvn -Ptest test

测试Rest Service示例cURL

最后,我们将提到,您还可以使用cURL测试文件上载:

$ curl -F file=@"/tmp/file.txt" http://localhost:8080/rest-file-manager/rest/file/upload
Successfully uploaded - file.txt

本Rest服务教程的源代码

您可以在这里找到这个rest服务教程的源代码:https://github.com/fmarchioni/mastertheboss/tree/master/javaee/rest-file-manager

相关文章