zoukankan      html  css  js  c++  java
  • 使用RestTemplate上传文件到远程接口

    有一个业务需求。需要将一个在线文件,在不经过本地存储转换的方式下同步到现有服务中。最终采纳的解决方案是使用Spring提供的RestTemplate来远程操作http服务,实现在线的文件同步上传。

    以下是文件上传的核心代码

    错误演示

    
        try{
                MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
                postParameters.add("type",type);
                postParameters.add("subType",subType);
    		 
                //获取文件名称
                URL openUrl = new URL(chenvaFilePath+fileUrl);
                URLConnection urlConnection = openUrl.openConnection();
                int fileLength = urlConnection.getContentLength();
                byte[]bytes = new byte[fileLength];
                // 读取流信息,一次性写入字节数组(与下面正确示例中不同之处)
                InputStream inputStream = urlConnection.getInputStream();
                inputStream.read(bytes);
                inputStream.close();
    
                HttpHeaders fileHeader = new HttpHeaders();
                fileHeader.setContentType(MediaType.parseMediaType(urlConnection.getContentType()));
                fileHeader.setContentDispositionFormData("upload", fileName);
                HttpEntity<ByteArrayResource> filePart = new HttpEntity<>(new
                        ByteArrayResource(bytes),fileHeader);
                postParameters.add("upload",filePart);
            } catch (Exception e) {
                updateSyncStatus(projectId,dictId,"4");
                throw new RuntimeException("文件上传错误");
            }
    
    
            HttpHeaders headers = new HttpHeaders();
    
            // 使用客户端的请求头,发起请求
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            headers.add("Cookie", newCookie);
            headers.add("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36");
            HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(postParameters, headers);
            restTemplate.setRequestFactory(new NoRedirectClientHttpRequestFactory());
    
            restTemplate.postForObject(UPLOAD_PATH, request, String.class) ;
    

    问题描述

          在使用上方代码实现文件上传时,是能够上传成功的。在进行文件下载时,出现错误。本业务程序中上传的是pdf文档,下载时文件大小都正确,内容是空白的。最后使用了ByteOutputStream进行缓存字节来实现的。可以正确下载。

    正确示例

    
         try{
                MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
                postParameters.add("type",type);
                postParameters.add("subType",subType);
                //获取文件名称
                URL openUrl = new URL(chenvaFilePath+fileUrl);
                URLConnection urlConnection = openUrl.openConnection();
                InputStream inputStream = openUrl.openStream();
                    
                // 将读取到的字节缓存到此处,用到的使用直接一次性获取
                ByteOutputStream byteOutputStream = new ByteOutputStream();
    
                int index = -1;
                byte[] bytes = new byte[1024];
                while ((index = inputStream.read(bytes)) != -1) {
                    byteOutputStream.write(bytes,0,index);
                }
                inputStream.close();
    
                HttpHeaders fileHeader = new HttpHeaders();
                fileHeader.setContentType(MediaType.parseMediaType(urlConnection.getContentType()));
                fileHeader.setContentDispositionFormData("upload", fileName);
                HttpEntity<ByteArrayResource> filePart = new HttpEntity<>(new
                        ByteArrayResource(byteOutputStream.getBytes()),fileHeader);
                postParameters.add("upload",filePart);
            } catch (Exception e) {
                throw new RuntimeException("文件上传错误");
            }
    
            HttpHeaders headers = new HttpHeaders();
    
            // 使用客户端的请求头,发起请求
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            headers.add("Cookie", newCookie);
            headers.add("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36");
            HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(postParameters, headers);
            restTemplate.setRequestFactory(new NoRedirectClientHttpRequestFactory());
    
            restTemplate.postForObject(UPLOAD_PATH, request, String.class) ;
    

    实现SimpleClientHttpRequestFactory类

    public class NoRedirectClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
    
        @Override
        protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
            // TODO Auto-generated method stub
            super.prepareConnection(connection, httpMethod);
            // 禁止自动重定向
            connection.setFollowRedirects(false);
        }
    }
    

        至此文件可以正常上传

    问题复现

        在使用maven进行打包编译时,提示错误,错误信息如下:

    com.sun.xml.internal.messaging.saaj.util程序包不存在
    

        于是乎开始了网上冲浪,在上线的紧要关头怎么能出现问题呢是吧。
        原因是在上面示例程序中使用了ByteOutputStream类,导致maven进行compiler的时候找不到该类信息,在maven编译打包时指定该类位置信息即可。

              <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                       <!--重要部分-->
                        <compilerArguments>
                            <bootclasspath>${env.JAVA_HOME}jrelib
    t.jar;${env.JAVA_HOME}jrelibjce.jar</bootclasspath>
                        </compilerArguments>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <encoding>${maven.compiler.encoding}</encoding>
                        <verbose/>
                    </configuration>
                </plugin>
    

        其中${env.JAVA_HOME}是java的系统变量,在maven中可以直接使用。使用mvn help:system可以系统的查看内置信息。

        还有一些maven的常用内置变量如下:

    ${basedir} 项目根目录
    ${project.build.directory} 构建目录,缺省为target
    ${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
    ${project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version} 当前版本
    ${project.packaging} 打包类型,缺省为jar
    
    充满鲜花的世界到底在哪里
  • 相关阅读:
    大并发服务器框架设计
    Flask框架(五) —— session源码分析
    Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析
    Flask框架(二)—— 反向解析、配置信息、路由系统、模板、请求响应、闪现、session
    Flask框架(一)—— Flask简介
    celery执行异步任务和定时任务
    爬虫(五)—— selenium模块启动浏览器自动化测试
    爬虫(四)—— 使用pyecharts展示数据
    爬虫(三)—— BeautifulSoup模块获取元素
    数据库(三)—— 数据库存储引擎、日志、备份、主从复制、高可用架构
  • 原文地址:https://www.cnblogs.com/aliases/p/13534406.html
Copyright © 2011-2022 走看看