Spring使用RestTemplate上传和下载文件
之前的文章写了 Android 运用 NanoHTTPD 上传和下载文件,当时测试时用的是 curl 命令上传下载文件,现在要使用 Spring 后端来上传和下载文件到 Android 端,服务器本地文件 <-------> Spring <-------> Android。
本文参考:Uploading MultipartFile with Spring RestTemplate 特别是它的 Github 代码 MultipartFileUploadClient.java
上传文件
创建一个类 MultipartFileUpload
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
@Service
public class MultipartFileUpload {
/**
* 上传单个文件
* @param filePath 要上传的文件的本地绝对路径
* @param serverUrl 接收上传文件的远端 URL
*/
public void uploadSingleFile(String filePath,String serverUrl) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",new FileSystemResource(filePath));
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);
System.out.println("Response code: " + response.getStatusCode());
}
/**
* 上传多个文件
* @param filePaths 要上传的多个文件的绝对路径 String[] 数组
* @param serverUrl 接收上传文件的远端 URL
*/
public void uploadMultipleFile(String[] filePaths,String serverUrl) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
for(String filePath : filePaths) {
body.add("file",new FileSystemResource(filePath));
}
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);
System.out.println("Response code: " + response.getStatusCode());
}
}HttpHeaders 是 HTTP 请求头对象,用于设置 HTTP 请求头部。
headers.setContentType(MediaType.MULTIPART_FORM_DATA); 是将请求设置为表单上传。
FileSystemResource 是 Spring 中以文件系统的绝对路径的方式访问静态资源。
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",new FileSystemResource(filePath));在请求主体,也就是表单中添加要上传的文件。
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(serverUrl, requestEntity, String.class);创建 HTTP 请求实体,并使用 RestTemplate 的 postForEntity 方法将其发出。
下载文件
下载文件就比较简单一点了,因为我们在之前的 Android 中对于下载文件,只要请求 http://ip:port/?download=xxx,xxx就代表要下载的文件。具体可以看看下面的 Android 代码
// HTTP GET
if (session.getMethod() == Method.GET) {
// 要下载的文件名称
String fileName = Objects.requireNonNull(session.getParameters().get("download")).get(0);
Log.d("fileName",fileName);
if(!fileName.isEmpty()) {
File downloadFile;
downloadFile = new File(PathUtils.getExternalDownloadsPath() + "/" + fileName);
return downloadFile(downloadFile);
}
}在 Spring 中创建 FileDownload 类
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.FileOutputStream;
import java.io.IOException;
@Service
public class FileDownload {
public void download(String fileName,String newFilePath) throws IOException {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
String serverUrl = "http://ip:port/?download=";
ResponseEntity<byte[]> response
= restTemplate.exchange(serverUrl + fileName, HttpMethod.GET,new HttpEntity<>(headers),byte[].class);
byte[] body = response.getBody();
try (FileOutputStream fos = new FileOutputStream(newFilePath)) {
fos.write(body);
}
}
}serverUrl 代表要下载的文件服务器地址。
ResponseEntity<byte[]> response = restTemplate.exchange(serverUrl + fileName, HttpMethod.GET,new HttpEntity<>(headers),byte[].class); 这里构造了一个字节数组的 HTTP 响应,因为在 Android 的下载文件代码中,文件下载的响应也是 private Response downloadFile(File file),所以将响应强制类型转换成了 byte[]。
byte[] body = response.getBody();
try (FileOutputStream fos = new FileOutputStream(newFilePath)) {
fos.write(body);
}将得到的字节数组写到文件,FileOutputStream()形参需要绝对路径地址,另外有个小 BUG ,如果 Android 中待下载的文件是没有内容的(0字节),下载到本地会抛出 byte[] 为空的异常。
本文其他参考:
Multipart File Upload Using Spring Rest Template + Spring Web MVC
评论已关闭