有一个业务需求。需要将一个在线文件,在不经过本地存储转换的方式下同步到现有服务中。最终采纳的解决方案是使用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}\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}是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