Java SpringRESTTemplateExecute()发布大文件并获得响应
这花了我相当长的时间,所以我想分享它。大部分信息来自SO,我想整合到这个地方 我的要求是使用RESTFul POST上传文件。由于可能是大文件,我想流文件。很明显,我希望能够读懂回复 我计划使用Jersey作为REST服务器,使用Spring的RestTemplate作为客户端(并用于测试)Java SpringRESTTemplateExecute()发布大文件并获得响应,java,spring,rest,stream,resttemplate,Java,Spring,Rest,Stream,Resttemplate,这花了我相当长的时间,所以我想分享它。大部分信息来自SO,我想整合到这个地方 我的要求是使用RESTFul POST上传文件。由于可能是大文件,我想流文件。很明显,我希望能够读懂回复 我计划使用Jersey作为REST服务器,使用Spring的RestTemplate作为客户端(并用于测试) 我面临的问题是将帖子分流并收到回复。我该怎么做?(反问-我回答!)我使用的是SpringBoot1.2.4。通过以下方式释放球衣: compile("org.springframework.boot:spr
我面临的问题是将帖子分流并收到回复。我该怎么做?(反问-我回答!)我使用的是SpringBoot
1.2.4。通过以下方式释放
球衣:
compile("org.springframework.boot:spring-boot-starter-jersey")
我用brilliant Spring Starter项目创建了这个项目(Spring ToolSuite>New
,或者我相信你可以通过一个网站来完成,毫无疑问IntelliJ也有这个功能)。并选择了“Jersey(JAX-RS)”选项。在gradlebuild.gradle
中,我还添加了依赖项:
compile('commons-io:commons-io:2.4')
我写了这个服务器端代码
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.me.fileStore.service.FileStoreService;
@RestController
@Path("/filestore")
public class FileStoreRestService {
private static Logger logger = LoggerFactory.getLogger(FileStoreRestService.class);
@Autowired
private FileStoreService fileStoreService;
@POST
@Path("upload")
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
public Response Upload(InputStream stream) throws IOException, URISyntaxException { //
String location = fileStoreService.upload(stream); // relative path
URI loc = new URI(location);
Response response = Response.created(loc).build();
System.out.println("POST - response: " + response + ", :" + response.getHeaders());
return response;
}
我遇到的最大麻烦是得到一个地点的回复
首先,我必须处理大文件流。正如你在下面的测试中所看到的,我遵循了这一点。无论我用HttpMessageConverterExtractor
尝试了什么,我都没有得到响应,正如那篇文章所说:
final HttpMessageConverterExtractor<String> responseExtractor =
new HttpMessageConverterExtractor<String>(String.class, restTemplate.getMessageConverters());
最终HttpMessageConverterExtractor响应Extractor=
新的HttpMessageConverterExtractor(String.class,restTemplate.getMessageConverters());
找到后,我写道:
私有静态类ResponseFromHeadersExtractor实现ResponseExtractor{
@凌驾
公共ClientHttpResponse提取数据(ClientHttpResponse响应){
System.out.println(“StringFromHeadersExtractor-response头文件:”+response.getHeaders());
返回响应;
}
}
这给了我一个测试:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = FileStoreApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port:9000")
public class FileStoreRestServiceTest {
private static Logger logger = LoggerFactory.getLogger(FileStoreRestServiceTest.class);
protected final Log logger2 = LogFactory.getLog(getClass());
String base = "http://localhost:9000/filestore";
private RestTemplate restTemplate = new TestRestTemplate();
@Test
public void testMyMethodExecute() throws IOException {
String content = "This is file contents\nWith another line.\n";
Path theTestFilePath = TestingUtils.getTempPath(content);
InputStream inputStream = Files.newInputStream(theTestFilePath);
String url = base + "/upload";
final RequestCallback requestCallback = new RequestCallback() {
@Override
public void doWithRequest(final ClientHttpRequest request) throws IOException {
request.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
IOUtils.copy(inputStream, request.getBody());
}
};
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
ClientHttpResponse response = restTemplate.execute(url, HttpMethod.POST, requestCallback,
new ResponseFromHeadersExtractor());
URI location = response.getHeaders().getLocation();
System.out.println("Location: " + location);
Assert.assertNotNull(location);
Assert.assertNotEquals(0, location.getPath().length());
}
private static class ResponseFromHeadersExtractor implements ResponseExtractor<ClientHttpResponse> {
@Override
public ClientHttpResponse extractData(ClientHttpResponse response) {
System.out.println("StringFromHeadersExtractor - response headers: " + response.getHeaders());
return response;
}
}
导入java.io.BufferedReader;
导入java.io.File;
导入java.io.FileReader;
导入java.io.IOException;
导入java.io.InputStream;
导入java.net.URI;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.nio.file.path;
导入java.util.HashMap;
导入java.util.Map;
导入org.apache.commons.io.IOUtils;
导入org.apache.commons.logging.Log;
导入org.apache.commons.logging.LogFactory;
导入org.hamcrest.matcherasert;
导入org.hamcrest.Matchers;
导入org.junit.Assert;
导入org.junit.Test;
导入org.junit.runner.RunWith;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.boot.test.IntegrationTest;
导入org.springframework.boot.test.SpringApplicationConfiguration;
导入org.springframework.boot.test.TestRestTemplate;
导入org.springframework.http.HttpMethod;
导入org.springframework.http.MediaType;
导入org.springframework.http.ResponseEntity;
导入org.springframework.http.client.ClientHttpRequest;
导入org.springframework.http.client.ClientHttpResponse;
导入org.springframework.http.client.SimpleClientHttpRequestFactory;
导入org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
导入org.springframework.test.context.web.WebAppConfiguration;
导入org.springframework.web.client.RequestCallback;
导入org.springframework.web.client.ResponseExtractor;
导入org.springframework.web.client.rest模板;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(类=FileStoreApplication.class)
@WebAppConfiguration
@集成测试(“服务器端口:9000”)
公共类FileStoreRestServiceTest{
私有静态记录器Logger=LoggerFactory.getLogger(FileStoreRestServiceTest.class);
受保护的最终日志logger2=LogFactory.getLog(getClass());
字符串基数=”http://localhost:9000/filestore";
私有RestTemplate RestTemplate=新TestRestTemplate();
@试验
public void testMyMethodExecute()引发IOException{
String content=“这是另一行的文件内容。\n”;
Path theTestFilePath=TestingUtils.getTempPath(内容);
InputStream InputStream=Files.newInputStream(测试文件路径);
字符串url=base+“/upload”;
final RequestCallback RequestCallback=new RequestCallback(){
@凌驾
public void doWithRequest(最终ClientHttpRequest请求)引发IOException{
request.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
copy(inputStream,request.getBody());
}
};
最终RestTemplate RestTemplate=新RestTemplate();
SimpleClientHttpRequestFactory requestFactory=新的SimpleClientHttpRequestFactory();
requestFactory.setBufferreRequestBody(false);
setRequestFactory(requestFactory);
ClientHttpResponse response=restTemplate.execute(url、HttpMethod.POST、requestCallback、,
新响应FromHeadersExtractor());
URI位置=response.getHeaders().getLocation();
System.out.println(“位置:+位置”);
Assert.assertNotNull(位置);
Assert.assertNotEquals(0,location.getPath().length());
}
私有静态类ResponseFromHeadersExtractor实现ResponseExtractor{
@凌驾
公共ClientHttpResponse提取数据(ClientHttpResponse响应){
System.out.println(“StringFromHeadersExtractor-response头文件:”+response.getHeaders());
返回响应;
}
}
在那个测试中,我需要将很多东西重构成一些服务。没有必要用
RequestCallback
来处理所有这些麻烦。只需使用一个
如果这样做有效(我将很快进行测试),那就太好了!
restemplate.exchange()
更适合自动处理响应,而无需ResponseFromHeadersExtractor
(我刚刚注意到我忘了添加它-因此现在将编辑我的答案).所以,是的,这似乎是一个更好的解决方案。我做了很多搜索,但没有找到这个。把它扔出去的力量!我无法让它工作。我得到了404,因为它似乎与PathResource不匹配。我
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = FileStoreApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port:9000")
public class FileStoreRestServiceTest {
private static Logger logger = LoggerFactory.getLogger(FileStoreRestServiceTest.class);
protected final Log logger2 = LogFactory.getLog(getClass());
String base = "http://localhost:9000/filestore";
private RestTemplate restTemplate = new TestRestTemplate();
@Test
public void testMyMethodExecute() throws IOException {
String content = "This is file contents\nWith another line.\n";
Path theTestFilePath = TestingUtils.getTempPath(content);
InputStream inputStream = Files.newInputStream(theTestFilePath);
String url = base + "/upload";
final RequestCallback requestCallback = new RequestCallback() {
@Override
public void doWithRequest(final ClientHttpRequest request) throws IOException {
request.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
IOUtils.copy(inputStream, request.getBody());
}
};
final RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
restTemplate.setRequestFactory(requestFactory);
ClientHttpResponse response = restTemplate.execute(url, HttpMethod.POST, requestCallback,
new ResponseFromHeadersExtractor());
URI location = response.getHeaders().getLocation();
System.out.println("Location: " + location);
Assert.assertNotNull(location);
Assert.assertNotEquals(0, location.getPath().length());
}
private static class ResponseFromHeadersExtractor implements ResponseExtractor<ClientHttpResponse> {
@Override
public ClientHttpResponse extractData(ClientHttpResponse response) {
System.out.println("StringFromHeadersExtractor - response headers: " + response.getHeaders());
return response;
}
}
PathResource pathResource = new PathResource(theTestFilePath);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(pathResource), String.class);
HttpHeaders responseHeaders = response.getHeaders();