汪的爱琪 2024-02-23 21:01 采纳率: 67.5%
浏览 10
已结题

阿里云OSS下载接收服务器端和客户端不一致数据量

首先就是报错信息
大致是

Premature end of Content-Length delimited message body (expected: 6,150; received: 3,589)

详细的就是

org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 6,150; received: 3,589)
    at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:178)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
    at java.base/java.util.zip.CheckedInputStream.read(CheckedInputStream.java:82)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:132)
    at com.aliyun.oss.event.ProgressInputStream.read(ProgressInputStream.java:118)
    at java.base/java.util.zip.CheckedInputStream.read(CheckedInputStream.java:82)
    at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:244)
    at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
    at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:343)
    at java.base/java.io.InputStream.readNBytes(InputStream.java:409)
    at java.base/java.io.InputStream.readAllBytes(InputStream.java:346)
    at com.codeCart.controller.FileController.download(FileController.java:46)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:261)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:189)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:917)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:829)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:840)


我的思路是前端发一个请求,后端根据这个去阿里云的oss服务器获取这个文件流,然后通知浏览器以下载方式打开,实现下载的目的
代码是

package com.codeCart.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyuncs.exceptions.ClientException;
import com.codeCart.listener.GetObjectProgressListener;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class FileDownloadUtils {
    //todo 能读字符串不能读图片,和FileController这样写很蠢,但是其他我也没办法
    //confused bis和osObject要是放在download方法里,在return之前,再注释掉这两个的close方法就能读远程txt文件,图片不行
    //confused 要是采用下面这种方式33行就会出错,try直接进finally执行close方法,再return一个null
//    private static BufferedInputStream bis;
//    private static OSSObject ossObject;
    public static List<Object> download(String objectName) throws Exception {
        String savePath = "D:\\"+objectName;
        String bucketName = "bytebazaar";
        String endpoint = "https://oss-cn-qingdao.aliyuncs.com";
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            ossClient.getObject(new GetObjectRequest(bucketName, objectName).
                            <GetObjectRequest>withProgressListener(new GetObjectProgressListener()),
                    new File(savePath));
            // 读取文件内容。
            System.out.println("Object content:");
            BufferedInputStream bis = new BufferedInputStream(ossObject.getObjectContent());
            List<Object> list = new ArrayList<>();
            list.add(bis);
            list.add(ossObject);
            return list;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
}


要是txt文件没什么问题,只要是其他的就是这样的问题,爆这个错

  • 写回答

1条回答 默认 最新

  • GISer Liu 2024-02-23 21:07
    关注

    该回答引用自GPT-3.5,由博主GISer Liu编写:

    根据你提供的问题描述和代码,报错信息显示预期接收到的数据量为6150字节,但实际接收到的数据量为3589字节,导致出现了"Premature end of
    Content-Length delimited message body"的异常。
    这种情况通常是由于数据在传输过程中发生了截断或丢失导致的。根据你的代码,我注意到你使用了阿里云的OSS服务来获取文件流,然后将文件流写入到本地文件中。可能的原因是在读取OSS对象内容时没有完全读取完整个文件流就被关闭了。这可能是由于流没有完全消耗或关闭引起的,导致数据未完全传输。
    为了解决这个问题,你可以尝试以下几点:

    1. 确保完全读取文件流:在获取OSS对象内容后,确保将文件流完全读取完毕再关闭流。你可以使用 IOUtils 或类似的工具类来帮助你完全读取流内容。
    2. 使用 try-with-resources:确保在读取完毕后及时关闭文件流。你可以使用 Java 7 引入的 try-with-resources 语句,这样可以确保资源在使用完毕后被正确关闭,不需要手动调用 close 方法。
    3. 检查网络连接和服务稳定性:确保你的网络连接稳定,阿里云OSS服务正常运行。有时网络波动或服务故障也可能导致数据传输不完整。
      以下是修改后的代码示例:
      javaCopy code
      import org.apache.commons.io.IOUtils;
      import com.aliyun.oss.model.OSSObject;
      public class FileDownloadUtils {
      public static List<Object> download(String objectName) throws Exception {
      String savePath = "D:\\" + objectName;
      String bucketName = "bytebazaar";
      String endpoint = "https://oss-cn-qingdao.aliyuncs.com";
      EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
      OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
      try {
      OSSObject ossObject = ossClient.getObject(bucketName, objectName);
      InputStream inputStream = ossObject.getObjectContent();
      // 使用IOUtils完全读取文件流
      byte[] content = IOUtils.toByteArray(inputStream);
      // 将文件内容写入本地文件
      Files.write(Paths.get(savePath), content);
      // 返回文件路径或其他信息
      return Collections.singletonList(savePath);
      } catch (OSSException oe) {
      // 处理异常
      } finally {
      // 关闭OSSClient
      if (ossClient != null) {
      ossClient.shutdown();
      }
      }
      return null;
      }
      }
      
      这样修改后,应该能够解决你遇到的数据量不一致导致的问题。

    如果该回答解决了您的问题,请采纳!如果没有,请参考以下方案进行修订

    用户答题指南

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月4日
  • 创建了问题 2月23日

悬赏问题

  • ¥15 有人会用py或者r画这种图吗
  • ¥15 MOD04_3K图像预处理
  • ¥15 [VASP]关于超胞大小和k 点网格的收敛性测试
  • ¥15 pip下载paddle2onnx离谱错误
  • ¥60 db2move nlzxams import 导出db2备份数据报错
  • ¥15 关于#python#的问题:全文总结功能咨询
  • ¥15 俄罗斯方块中无法同时消除多个满行
  • ¥15 使用gojs3.0,如何在nodeDataArray设置好text的位置,再go.TextBlock alignment中进行相应的改变
  • ¥15 psfusion图像融合指标很低
  • ¥15 银河麒麟linux系统如何修改/etc/hosts权限为777