从Spring @Controller返回具有OutputStream的文件


问题内容

我想从Spring控制器返回文件。我已经有了可以给我OutputStream的任何实现的API,然后需要将其发送给用户。

所以流程是这样的:

获取输出流 - >服务将此输出流传递给控制器 - >控制器必须将其发送给用户

我想我需要输入流来做到这一点,而且我还发现了如下所示的Apache Commons api功能:

IOUtils.copy(InputStream is, OutputStream os)

但问题是,它将其转换为另一面->不是从 osis ,而是从 isos

编辑

明确一点,因为我看到答案没有正确:
我使用Dropbox api并在OutputStream中接收文件,并且我希望在输入一些URL时将此输出流发送给用户

FileOutputStream outputStream = new FileOutputStream(); //can be any instance of OutputStream
DbxEntry.File downloadedFile = client.getFile("/fileName.mp3", null, outputStream);

那就是为什么我在谈论将 outputstream 转换为 inputstream
,但是却不知道该怎么做。此外,我认为有更好的方法来解决此问题(也许以某种方式从输出流返回字节数组)

我试图通过参数将servlet输出流[response.getOutputstream()]传递给从Dropbox下载文件的方法,但它根本没有用

编辑2

我的应用程序的“流程”是这样的:@Joeblade

  1. 用户输入网址: / download / {file_name}

  2. Spring Controller捕获URL并调用 @Service层以下载 文件并将其传递给该控制器:

@RequestMapping(value = "download/{name}", method = RequestMethod.GET)
public void getFileByName(@PathVariable("name") final String name, HttpServletResponse response) throws IOException {
 response.setContentType("audio/mpeg3");
 response.setHeader("Content-Disposition", "attachment; filename=" + name);
 service.callSomeMethodAndRecieveDownloadedFileInSomeForm(name); // <- and this file(InputStream/OutputStream/byte[] array/File object/MultipartFile I dont really know..) has to be sent to the user
}
  1. 现在@Service调用 Dropbox API, 并通过指定的 file_name 下载文件,并将其全部放入OutputStream,然后将其传递(以某种形式。也许是OutputStream,byte []数组或任何其他对象-我不知道这是更好地使用)给控制器:
public SomeObjectThatContainsFileForExamplePipedInputStream callSomeMethodAndRecieveDownloadedFileInSomeForm(final String name) throws IOException {
 //here any instance of OutputStream - it needs to be passed to client.getFile lower (for now it is PipedOutputStream)
 PipedInputStream inputStream = new PipedInputStream(); // for now
 PipedOutputStream outputStream = new PipedOutputStream(inputStream);


 //some dropbox client object
 DbxClient client = new DbxClient();
 try {
     //important part - Dropbox API downloads the file from Dropbox servers to the outputstream object passed as the third parameter
     client.getFile("/" + name, null, outputStream);
 } catch (DbxException e){
     e.printStackTrace();
 } finally {
     outputStream.close();
 }
 return inputStream;
}
  1. 控件接收到文件 (我完全不知道,就像我上面所说的那样),然后 将其 传递 给用户

因此,事情是OutputStream通过调用dropboxClient.getFile()方法接收下载的文件,然后OutputStream将包含下载文件的文件发送给用户,该怎么做?


问题答案:

您可以使用ByteArrayOutputStreamByteArrayInputStream。例:

// A ByteArrayOutputStream holds the content in memory
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

// Do stuff with your OutputStream

// To convert it to a byte[] - simply use
final byte[] bytes = outputStream.toByteArray();

// To convert bytes to an InputStream, use a ByteArrayInputStream
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);

您可以 其他 流对 执行相同操作。例如文件流:

// Create a FileOutputStream
FileOutputStream fos = new FileOutputStream("filename.txt");

// Write contents to file

// Always close the stream, preferably in a try-with-resources block
fos.close();

// The, convert the file contents to an input stream
final InputStream fileInputStream = new FileInputStream("filename.txt");

而且,使用Spring MVC时,您绝对可以返回byte[]包含您的文件的。只要确保您使用注释您的回复即可@ResponseBody。像这样:

@ResponseBody
@RequestMapping("/myurl/{filename:.*}")
public byte[] serveFile(@PathVariable("file"} String file) throws IOException {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    DbxEntry.File downloadedFile = client.getFile("/" + filename, null, outputStream);
    return outputStream.toByteArray();
}