用JAVA下载HTTP文件时遇到问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JAVA下载HTTP文件时遇到问题相关的知识,希望对你有一定的参考价值。
我用JAVA写一个下载文件的工具,但是遇到了问题,就是我下载一个文件时,它过小,不足1KB,只有700多字节,但我获得它的“Content-Length”有16字节,这样搞的我下载下来的文件就只有16字节大小,文件被修改了,导致打不开了。这种情况该怎么办去下载呢?因为下载的文件(压缩包)查看了下
像这个文件的content-length为31118,下载顺利,解压也没问题
我下载另外一个文件(压缩包)时,URL连接后面的201407改为20140904,content-length为16,我用InputStream input = httpConnection.getInputStream()来传输,input.avalilable大小也为16字节,这样就导致了所有很小的文件全部设置大小为16字节了,我甚至用byte[1]设置下载大小,然后对流进行保存,用read函数,这样都无法避免
但是我用浏览器下载后发下压缩包大小为700多字节,占用空间大小为4KB
百思不得其解,希望大神解答。
这种情况改怎么下载呢?
import java.io.*;
public class URLConnectionDemo
public static void main(String[] args)throws Exception
URL url = new URL("http://www.scp.edu.cn/pantoschoolzz/BG/Bord/Message/DownloadMessageAttachment.aspx?ID=215");
URLConnection uc = url.openConnection();
String fileName = uc.getHeaderField(6);
fileName = URLDecoder.decode(fileName.substring(fileName.indexOf("filename=")+9),"UTF-8");
System.out.println("文件名为:"+fileName);
System.out.println("文件大小:"+(uc.getContentLength()/1024)+"KB");
String path = "D:"+File.separator+fileName;
FileOutputStream os = new FileOutputStream(path);
InputStream is = uc.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while((len=is.read(b))!=-1)
os.write(b,0,len);
os.close();
is.close();
System.out.println("下载成功,文件保存在:"+path);
//给你一个下载的例子吧,仅供参考。
参考技术A 首先我们观察 HTTP 通信过程发现服务端确实说明了大小是 31118 字节,对吧?似乎程序得到 Content-Length 的方法有问题,这个过程中有没有发生重定向的事情? 参考技术B 你要flush一下啊,骚年
使用角度 $http 或 jquery.ajax 下载二进制文件时遇到问题
【中文标题】使用角度 $http 或 jquery.ajax 下载二进制文件时遇到问题【英文标题】:Trouble downloading binary file with angular $http or jquery.ajax 【发布时间】:2016-01-13 00:56:12 【问题描述】:我的问题是我在客户端获取了错误大小的文件。这是我的@Controller ...
@RequestMapping(value = "/download/id", method = RequestMethod.GET)
public ResponseEntity<?> download(final HttpServletRequest request,
final HttpServletResponse response,
@PathVariable("id") final int id) throws IOException
try
// Pseudo-code for retrieving file from ID.
Path zippath = getZipFile(id);
if (!Files.exists(zippath))
throw new IOException("File not found.");
ResponseEntity<InputStreamResource> result;
return ResponseEntity.ok()
.contentLength(Files.size(zippath))
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource(new FileInputStream(zippath.toFile())));
catch (Exception ex)
// ErrorInfo is another class, unimportant
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorInfo(ex));
...这是我使用 angular-file-saver 的客户端代码...
$http(url: "export/download/" + exportitem.exportId, withCredentials: true)
.then(function(response)
function str2bytes(str)
var bytes = new Uint8Array(str.length);
for (var i=0; i<str.length; i++)
bytes[i] = str.charCodeAt(i);
return bytes;
var blob = new Blob([str2bytes(response.data)], type: 'application/octet-stream');
FileSaver.saveAs(blob, "download.zip");
, $exceptionHandler);
原始文件为 935673 字节,但 response.data 为 900728,并将其通过转换传递给 Uint8Array 会产生一个大小为 900728 的 Blob。无论哪种方式,生成的保存文件都是 900728 字节(34945 字节)。此外,它所写的内容也不完全相同。它似乎有点臃肿,但最后一部分似乎被截断了。有什么想法我可能做错了吗?
更新
我刚刚将我的控制器方法更新为以下并得到完全相同的结果。咕噜。
@RequestMapping(value = "/download/id", method = RequestMethod.GET)
public void download(final HttpServletRequest request,
final HttpServletResponse response,
@PathVariable("id") final int id) throws IOException
// Pseudo-code for retrieving file from ID.
Path zippath = getZipFile(id);
if (!Files.exists(zippath))
throw new IOException("File not found.");
response.setContentType("application/zip");
response.setHeader("Content-Disposition",
"attachment; filename=download.zip");
InputStream inputStream = new FileInputStream(zippath.toFile());
org.apache.commons.io.IOUtils.copy(inputStream, response.getOutputStream());
response.flushBuffer();
inputStream.close();
【问题讨论】:
zippath.toFile()
会发生什么?
将 Path 对象转换为 File 对象,以便我可以在 FileInputStream 中使用它。
【参考方案1】:
所以问题原来是 Angular 的 $http 服务。我还尝试了 jQuery 的 ajax 方法。两者都给出了相同的结果。如果我改为使用本机 XMLHttpRequest 它可以正常工作。所以 Java 代码是正确的。我首先通过将文件直接暴露在互联网上来验证这一点,然后使用 curl 和直接在浏览器中访问我设法下载了正确大小的文件。然后我找到了这个解决方案,这样我也可以通过 javascript 下载文件。
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.withCredentials = true;
xhr.onreadystatechange = function ()
if (xhr.readyState === 4)
var blob = xhr.response;
FileSaver.saveAs(blob, filename);
;
xhr.send();
为什么 Angular 或 jQuery 会给出错误的结果?我仍然不知道,但是如果有人希望给出使用这些答案的答案,将不胜感激。
【讨论】:
同样的事情。不知道为什么 jquery/angular 会增加文件大小并破坏数据。【参考方案2】:响应类型:blob 做了一个 zip 文件的技巧
角度 2 +
this.http.get('http://localhost:8080/export', responseType: ResponseContentType.Blob )
.subscribe((res: any) =>
const blob = new Blob([res._body], type: 'application/zip' );
saveAs(blob, "fileName.zip");
【讨论】:
【参考方案3】:我刚刚偶然发现 $http 请求中的“responseType”,您可能正在寻找“blob”:https://docs.angularjs.org/api/ng/service/$http#usage
【讨论】:
以上是关于用JAVA下载HTTP文件时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章