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이 컴파일러 수행시 이러한 유형의 정보를 찾게되는데, 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}\jre\lib\rt.jar;${
    
    env.JAVA_HOME}\jre\lib\jce.jar</bootclasspath>
                    </compilerArguments>
                    <source>${
    
    java.version}</source>
                    <target>${
    
    java.version}</target>
                    <encoding>${
    
    maven.compiler.encoding}</encoding>
                    <verbose/>
                </configuration>
            </plugin>

    그중 $ {env.JAVA_HOME}은 자바 시스템 변수로 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

추천

출처blog.csdn.net/qq_37640410/article/details/108336232