HTTP状态406–;不可接受[使用spring 4.3.x+;Java 8从后端流式传输大量数据]
我使用的是SpringMVC4.3.x、Java8和Tomcat7 代码:HTTP状态406–;不可接受[使用spring 4.3.x+;Java 8从后端流式传输大量数据],java,spring,spring-mvc,java-8,Java,Spring,Spring Mvc,Java 8,我使用的是SpringMVC4.3.x、Java8和Tomcat7 代码: @Controller public class StreamRecordsController { @RequestMapping(value = "/streamrecords", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE, produces = "application/octet-stream")
@Controller
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE,
produces = "application/octet-stream")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() throws FileNotFoundException {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
package com.emg.server.controller.rest;
import java.io.IOException;
import java.io.OutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords")
@ResponseBody
public StreamingResponseBody export() {
return new StreamingResponseBody() {
@Override
public void writeTo (OutputStream out) throws IOException {
for (int i = 0; i < 1000; i++) {
out.write((Integer.toString(i) + " - ")
.getBytes());
out.flush();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}
package com.emg.server.controller.rest;
import java.io.File;
import java.nio.file.Files;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
@控制器
公共类StreamRecordsController{
@RequestMapping(value=“/streamrecords”,method=RequestMethod.GET,consumes=MediaType.ALL_值,
products=“应用程序/八位字节流”)
@应答器
公共响应属性导出()引发FileNotFoundException{
File File=新文件(“C:\\Users\\Ankur\\sample.pdf”);
StreamingResponseBody responseBody=输出流->{
copy(file.toPath(),outputStream);
};
返回ResponseEntity.ok()
.header(HttpHeaders.CONTENT\u处置,“附件;文件名=通用文件名\u name.pdf”)
.contentType(MediaType.APPLICATION\u八位字节\u流)
.主体(响应体);
}
}
例外情况:
@Controller
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE,
produces = "application/octet-stream")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() throws FileNotFoundException {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
package com.emg.server.controller.rest;
import java.io.IOException;
import java.io.OutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords")
@ResponseBody
public StreamingResponseBody export() {
return new StreamingResponseBody() {
@Override
public void writeTo (OutputStream out) throws IOException {
for (int i = 0; i < 1000; i++) {
out.write((Integer.toString(i) + " - ")
.getBytes());
out.flush();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}
package com.emg.server.controller.rest;
import java.io.File;
import java.nio.file.Files;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
邮差快照
问题:
@Controller
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE,
produces = "application/octet-stream")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() throws FileNotFoundException {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
package com.emg.server.controller.rest;
import java.io.IOException;
import java.io.OutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords")
@ResponseBody
public StreamingResponseBody export() {
return new StreamingResponseBody() {
@Override
public void writeTo (OutputStream out) throws IOException {
for (int i = 0; i < 1000; i++) {
out.write((Integer.toString(i) + " - ")
.getBytes());
out.flush();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}
package com.emg.server.controller.rest;
import java.io.File;
import java.nio.file.Files;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
我在这里遗漏了什么?你似乎遗漏了两件事: 首先,您的代码将返回
MediaType.APPLICATION\u OCTET\u STREAM
作为内容类型。如果您告诉spring,export()
方法正在生成该类型,那就太好了。您可以使用@RequestMapping
的products
属性来执行此操作
第二件事是,您的浏览器没有要求应用程序\u八位字节\u流
——您可以通过接受
标题值看到这一点APPLICATION\u OCTET\u STREAM
映射到APPLICATION/OCTET STREAM
-您从浏览器发出的请求需要包含在Accept
头值中,这样Spring将能够识别应该在控制器中调用的方法
编辑:修复后,请查看可替代@Controller
使用的@RestController
注释-您不必添加@ResponseBody
注释,因为默认情况下它将包含在内。还可以查看HTTP GET方法的@GetMapping
覆盖的@RequestMapping
注释。406不可接受
根据请求中发送的accept标头,由请求标识的资源只能生成具有不可接受内容特征的响应实体
尝试在控制器方法中使用生成注释:
@Produces({MediaType.APPLICATION_JSON})
发生在您身上的可能是Spring MVC错误。对于浏览器&它也因浏览器而异-请求中的Accept标头必须具有正确的值。您可能在不同的浏览器中获得不同的行为,并且您的代码可能在swagger UI中工作 根据您的屏幕截图,您的Accept标头与响应类型不匹配,它应该是
*/*
,因为您的代码非常特殊,您不接受任何输入,这在REST world中是罕见的
因此,我建议在映射中添加消费,如下所示&看看它是否有效
@RequestMapping(value=“/streamrecords”,method=RequestMethod.GET,consumes=MediaType.ALL\u value)
并确保请求中的Accept标头带有值-
*/*
此错误表示客户端(如浏览器)希望服务器发送某种类型的内容X(通过Accept头,如application/json),但服务器不在给定端点上提供此类内容(如仅生成XML)
在您的情况下,您正在“接受”多种格式,但它们都不是
application/octet-stream
,这就是您声明服务器将在@RequestMapping(products=“application/octet-stream”)
注释中返回的格式。将其包含在您的Accept
标题浏览器端。最后,我能够解决这个问题,它现在帮助我使用Spring 4.3.x将大量数据从后端流到前端,正如我在文章中提到的那样。以下是指导您成功执行程序的要点
下面的过程非常有效,您甚至可以在后端对大量数据进行分页(可以是hibernate、Mongo java驱动程序、cassandra java驱动程序等),并继续流式传输数据,除非您的db操作完成。在一些领域,如制造业、保险业、物流业等,您需要这样的实用程序,最终用户希望从服务器以CSV、JSON等形式获取大量数据,以分析原始数据
@EnableWebMvc
catalina.log
中看到此错误:pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
@Controller
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE,
produces = "application/octet-stream")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() throws FileNotFoundException {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
package com.emg.server.controller.rest;
import java.io.IOException;
import java.io.OutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords")
@ResponseBody
public StreamingResponseBody export() {
return new StreamingResponseBody() {
@Override
public void writeTo (OutputStream out) throws IOException {
for (int i = 0; i < 1000; i++) {
out.write((Integer.toString(i) + " - ")
.getBytes());
out.flush();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
}
}
package com.emg.server.controller.rest;
import java.io.File;
import java.nio.file.Files;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@Controller
@EnableWebMvc
public class StreamRecordsController {
@RequestMapping(value = "/streamrecords", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
@ResponseBody
public ResponseEntity<StreamingResponseBody> export() {
File file = new File("C:\\Users\\Ankur\\sample.pdf");
StreamingResponseBody responseBody = outputStream -> {
Files.copy(file.toPath(), outputStream);
};
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=generic_file_name.pdf")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
}
包com.emg.server.controller.rest;
导入java.io.IOException;
导入java.io.OutputStream;
导入org.springframework.stereotype.Controller;
导入org.springframework.web.bind.annotation.RequestMapping;
导入org.springframework.web.bind.annotation.ResponseBody;
导入org.springframework.web.servlet.config.annotation.EnableWebMvc;
导入org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
@控制器
@EnableWebMvc
公共类StreamRecordsController{
@请求映射(value=“/streamrecords”)
@应答器
公共StreamIngregatePonsebody导出(){
返回新的StreamingResponseBody(){
@凌驾
public void writeTo(OutputStream out)引发IOException{
对于(int i=0;i<1000;i++){
out.write((Integer.toString(i)+“-”)
.getBytes());
out.flush();
试一试{
睡眠(5);
}捕捉(中断异常e){