Spring REST - 正在下载损坏/空白文件
Posted
技术标签:
【中文标题】Spring REST - 正在下载损坏/空白文件【英文标题】:Spring REST - Damaged/Blank File being downloaded 【发布时间】:2018-10-07 03:20:28 【问题描述】:我正在尝试创建一个端点来呈现/提供 PDF 文件。 我已通过以下链接构建 API,但仍面临一些问题。
link 1
link 2
以下是我的代码:
byte[] targetArray = null;
InputStream is = null;
InputStream objectData = object.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(objectData));
char[] charArray = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = reader.read(charArray, 0, charArray.length)) != -1)
builder.append(charArray, 0, numCharsRead);
reader.close();
objectData.close();
object.close();
targetArray = builder.toString().getBytes();
is = new ByteArrayInputStream(targetArray);
return ResponseEntity.ok().contentLength(targetArray.length).contentType(MediaType.APPLICATION_PDF)
.cacheControl(CacheControl.noCache()).header("Content-Disposition", "attachment; filename=" + "testing.pdf")
.body(new InputStreamResource(is));
当我使用邮递员访问我的 API 时,我可以下载 PDF 文件,但问题是它完全是空白的。可能是什么问题?
【问题讨论】:
嗯...为什么要将PDF读入char
的数组,将其转换为String
,然后从字符串中提取字节?你明白字符数据和二进制数据的区别吧?
另外,既然您的数据已经有一个InputStream
,为什么不使用您提到的第一个链接中的InputStreamResource
?
实际上我正在尝试从远程位置获取 PDF 文件的内容,该位置正在流式传输我的 PDF 文件内容。
很公平,但是由于您使用InputStream
对其进行操作,因此对您来说应该是透明的。当您直接返回 InputStreamResource
包装 objectData
时会发生什么?为什么你觉得你需要所有的中间步骤?
其实InputStream是S3ObjectInputStream
。
【参考方案1】:
从服务器下载文件有多种方式,您可以使用ResponseEntity<InputStreamResource>
、HttpServletResponse
。以下是两种下载方式。
@GetMapping("/download1")
public ResponseEntity<InputStreamResource> downloadFile1() throws IOException
File file = new File(FILE_PATH);
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=" + file.getName())
.contentType(MediaType.APPLICATION_PDF).contentLength(file.length())
.body(resource);
或
您可以使用StreamingResponseBody
下载大文件。在这种情况下,服务器将数据写入OutputStream
,同时浏览器读取数据,这意味着它是并行的。
@RequestMapping(value = "downloadFile", method = RequestMethod.GET)
public StreamingResponseBody getSteamingFile(HttpServletResponse response) throws IOException
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"demo.pdf\"");
InputStream inputStream = new FileInputStream(new File("C:\\demo-file.pdf"));
return outputStream ->
int nRead;
byte[] data = new byte[1024];
while ((nRead = inputStream.read(data, 0, data.length)) != -1)
System.out.println("Writing some bytes..");
outputStream.write(data, 0, nRead);
;
【讨论】:
【参考方案2】:你可以尝试使用apache commons IOUtils。为什么要重新发明***:) 1.打开与远程服务器的连接 2.将inputStream复制到目标文件outputStream。
public void downloadFileFromRemoteLocation(String serverlocation, File destinationFile) throws IOException
try (FileOutputStream fos = new FileOutputStream( destinationFile ))
URL url = new URL(serverlocation);
URLConnection connection = url.openConnection();
IOUtils.copy( connection.getInputStream(), fos);
如果您只想坚持 Java,请查看下面的 sn-p
try
// Get the directory and iterate them to get file by file...
File file = new File(fileName);
if (!file.exists())
context.addMessage(new ErrorMessage("msg.file.notdownloaded"));
context.setForwardName("failure");
else
response.setContentType("APPLICATION/DOWNLOAD");
response.setHeader("Content-Disposition", "attachment"+
"filename=" + file.getName());
stream = new FileInputStream(file);
response.setContentLength(stream.available());
OutputStream os = response.getOutputStream();
os.close();
response.flushBuffer();
catch (IOException e)
e.printStackTrace();
finally
if (stream != null)
try
stream.close();
catch (IOException e)
e.printStackTrace();
【讨论】:
以上是关于Spring REST - 正在下载损坏/空白文件的主要内容,如果未能解决你的问题,请参考以下文章
通过 REST API 上传多部分文件会损坏文件并增加文件大小
使用 REST API 上传到 Azure Blob 存储时,Zip 档案损坏