求助:HttpURLConnection读取输入流的时候报错!

「已注销」
博客专家认证
2017-08-31 03:27:49
有这么一个需求:
在项目A中用到B服务器的图片服务器,外网无法直接访问那个URL,所以只能在A服务器写一个中转的类,类似于桥接或者中转的思路来转换我们的输入输出流。这个类如下:

@Controller
@RequestMapping("/fileBridge")
@Scope("request")
public class FileBridgeCtrl {

private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 在线查看文件
* @param fileid 文件id
* @param response
* @throws IOException
*/
@RequestMapping(value = "/download", method = RequestMethod.GET)
public void online(String path, HttpServletRequest request, HttpServletResponse response) throws IOException {
int index = path.lastIndexOf('.');
String type = path.substring(index);
logger.debug("文件类型=" + type);

this.GetImage(request, response, path);
}

/**
* 获取图片
* @param request
* @param response
*/
public void GetImage(HttpServletRequest request, HttpServletResponse response, String path){
InputStream inStream = null;
OutputStream os = null;

try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
conn.setRequestProperty("connection", "Keep-Alive");
conn.connect();
inStream = conn.getInputStream();//通过输入流获取图片数据
String contentType = conn.getContentType();
logger.debug("contentType : " + contentType);

byte data[] = readInputStream(inStream);
inStream.read(data); //读数据

response.setContentType(contentType); //设置返回的文件类型
os = response.getOutputStream();
os.write(data);
os.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(inStream != null) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

public static byte[] readInputStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while( (len=inStream.read(buffer)) != -1 ){
outStream.write(buffer, 0, len);
}
return outStream.toByteArray();
}

}

这是一个Spring MVC的Controler,重点是哪个GetImage方法,本方法本来只是用来中转图片的,所以取名叫做:GetImage,现在可以中转其他文件类型的文档。
该类存在一个之类的BUG:当用户传递过来的url带有中文字符的时候,将报错,报错信息如下:

java.io.FileNotFoundException: http://xx.xx.xx.xx/uploads/1749点火程序27.jpg
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1836)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at com.rfsdd2.dqzt.ctrl.FileBridgeCtrl.GetImage(FileBridgeCtrl.java:64)
at com.rfsdd2.dqzt.ctrl.FileBridgeCtrl.online(FileBridgeCtrl.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.rfsdd2.dqzt.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:26)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)


上诉传入的url是:http://xx.xx.xx.xx.xx/uploads/1749点火程序27.jpg
如果传入的url是:http://xx.xx.xx.xx/uploads/170627101626.JPG则图片能输出到浏览器端。

我百度过了,排除已下几种原因:
1.代理原因,因为报错的那个URL我直接输入浏览器,能够显示图片。而且那个不带中文字符的ulr在程序中不报错。
2.http header参数不足,我怀疑我的程序中给的http header头参数不足,所以多给了几个参数,结果还是报错。
...全文
1182 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
觉得我是谁呢 2019-01-01
  • 打赏
  • 举报
回复
引用 2 楼 54powerman 的回复:


URL url = new URL(path);

//改为:

URL url = new URL(new URI(path).toASCIIString());


非常感谢,我的也解决了。
一个治疗术 2017-08-31
  • 打赏
  • 举报
回复
引用 6 楼 zhang5476499 的回复:
[quote=引用 5 楼 aschouas 的回复:] [quote=引用 3 楼 zhang5476499 的回复:] [quote=引用 1 楼 aschouas 的回复:]
 
private String charset = "utf-8";

httpURLConnection.setRequestProperty("Accept-Charset", charset);
加过这个吗
刚把这个加上,还是报错![/quote] online()方法里面的路径是否已经乱码了,可以debug看一下[/quote]传到online方法的时候,那个url还不是乱码,显示正常的,2楼个的方法能解决![/quote] 我以前这么写没出过问题,学到了哈
「已注销」 2017-08-31
  • 打赏
  • 举报
回复
引用 5 楼 aschouas 的回复:
[quote=引用 3 楼 zhang5476499 的回复:] [quote=引用 1 楼 aschouas 的回复:]
 
private String charset = "utf-8";

httpURLConnection.setRequestProperty("Accept-Charset", charset);
加过这个吗
刚把这个加上,还是报错![/quote] online()方法里面的路径是否已经乱码了,可以debug看一下[/quote]传到online方法的时候,那个url还不是乱码,显示正常的,2楼个的方法能解决!
一个治疗术 2017-08-31
  • 打赏
  • 举报
回复
引用 3 楼 zhang5476499 的回复:
[quote=引用 1 楼 aschouas 的回复:]
 
private String charset = "utf-8";

httpURLConnection.setRequestProperty("Accept-Charset", charset);
加过这个吗
刚把这个加上,还是报错![/quote] online()方法里面的路径是否已经乱码了,可以debug看一下
「已注销」 2017-08-31
  • 打赏
  • 举报
回复
引用 2 楼 54powerman 的回复:


URL url = new URL(path);

//改为:

URL url = new URL(new URI(path).toASCIIString());
可以了,谢谢!
「已注销」 2017-08-31
  • 打赏
  • 举报
回复
引用 1 楼 aschouas 的回复:
 
private String charset = "utf-8";

httpURLConnection.setRequestProperty("Accept-Charset", charset);
加过这个吗
刚把这个加上,还是报错!
54powerman 2017-08-31
  • 打赏
  • 举报
回复


URL url = new URL(path);

//改为:

URL url = new URL(new URI(path).toASCIIString());
一个治疗术 2017-08-31
  • 打赏
  • 举报
回复
 
private String charset = "utf-8";

httpURLConnection.setRequestProperty("Accept-Charset", charset);
加过这个吗

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧