Servlets 无法下载小文件,但可以下载大文件

Servlets 无法下载小文件,但可以下载大文件,servlets,grails,amazon-s3,groovy,Servlets,Grails,Amazon S3,Groovy,我正在使用下面的代码从S3下载文件。该代码适用于中到大的文件大小,但是,对于3kb的非常小的文件大小-TXT文件中的一行,下载失败 //控制器 def download() { Request request = Request.get(params.int("id")) response.setContentType("application/octet-stream") myService.downloadFileFromS3(request.origFileName, r

我正在使用下面的代码从S3下载文件。该代码适用于中到大的文件大小,但是,对于3kb的非常小的文件大小-TXT文件中的一行,下载失败

//控制器

def download() {
   Request request = Request.get(params.int("id"))
   response.setContentType("application/octet-stream")
   myService.downloadFileFromS3(request.origFileName, response)
}


void downloadFileFromS3(String fileName, HttpServletResponse response) {
    String fullFileNameWithExtension = fileName
    response.setHeader("Content-disposition", "attachment;filename=${fullFileNameWithExtension}")
    InputStream is = getS3Client().getObject(getBucketName(), fullFileNameWithExtension).getObjectContent()
    OutputStream outputStream = response.getOutputStream()
    byte[] buffer = new byte[1024];
    int length
    log.info("This is the length: " + length)
    while ((length = is.read(buffer)) != -1) {
        log.info("Came here with length: " + length)
        outputStream.write(buffer, 0, length)
    }
    is.close()
}
小文件的注销:

This is the length: 0
Came here with length: 15
GroovyPagesServlet:  "/WEB-INF/grails-app/views/request/download.gsp" not found
大型文件的日志输出:

This is the length: 0
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 1024
Came here with length: 531

因此,对于小文件,它似乎在寻找download.gsp视图。但它不应该寻求这种观点,因为我在回复中加入了一些东西

我认为约书亚·摩尔的评论可能是正确的答案

但是,我建议稍微重构代码,使其更干净一点

1首先,尽量避免将与web相关的对象(如请求、响应)传递到服务层。您可以通过让服务层方法返回OutputStream来重构它。在服务方法中,您只需创建一个ByteArrayOutputStream,它将保存从S3下载的文件的内容。然后将该输出流的内容写入控制器内的response.outputStream。这将使测试和保持代码干燥变得更容易,也就是说,您现在可以使用此方法从S3下载文件,而无需将文件内容写入响应

2另外,您应该重命名控制器方法中声明的请求变量,因为请求是一个隐式变量

我的服务

霉菌控制者


它是如何失败的?提出了哪些例外情况?你犯了什么错误?您需要提供更多详细信息。@Joshuamore我已更新了更多详细信息。请在从该方法返回之前尝试outputStream.flush。
def amazonWebService
OutputStream downloadFileFromS3(String filename) {
    InputStream inputStream = amazonWebService.getS3("us-east-1").getObject(getBucketName(), filename).getObjectContent()
    OutputStream outputStream = new ByteArrayOutputStream()
    byte[] buffer = new byte[1024];
    int length
    log.info("This is the length: " + length)
    while ((length = inputStream.read(buffer)) != -1) {
        log.info("Came here with length: " + length)
        outputStream.write(buffer, 0, length)
    }
    if (inputStream) inputStream.close()
    return outputStream
}
    def myService
    def download() {

        // NOTE: I would recommend not using `request` as a variable 
        // name here since it's already an implicit variable 
        Request thatOtherRequest = Request.get(params.int("id")) 

        def filename = thatOtherRequest.origFileName
        def outputStream = myService.downloadFileFromS3UsingAwsSdk(filename)

        response.setContentType("application/octet-stream")
        response.setHeader("Content-disposition", "attachment;filename=${filename}")
        response.outputStream << outputStream
        response.outputStream.flush()
        return
    }