网站首页 > java教程 正文
.
概述
本文的目的是展示如何使用 Http Client API 从 REST 端点上传/下载文件内容。
让我们回顾一下调用 Web 资源的步骤,因为此过程与上传/下载文件数据相同。
- 如果需要,将创建 HttpClient 对象并进一步配置(超时、身份验证器、http 版本、followRedirects...)
- Http 请求是通过 URL 创建的。可以选择设置其他功能。例如,http 方法、http 标头、超时和 http 版本。
- 然后,HttpResponse 不是直接创建的,而是作为使用 HttpClient 发送 HttpRequest 的结果返回的。完成后,可以从中检查状态代码和正文(如果有)。
现在,让我们继续下载文件用例。
下载文件内容
我们将按照上述步骤来执行此操作。但首先,让我们看看后端。端点以字节数组的形式发回文件内容
@RestController
@RequestMapping("api/v1/documents")
public class DocumentController {
// ommited code here
@GetMapping(value = "/{documentId}")
ResponseEntity<Resource> downloadDocument(@PathVariable Long
documentId) {
Optional<Document> document = documentRepo.findById(documentId);
if (document.isEmpty())
return ResponseEntity.notFound().build();
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType(
document.get().getType()))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;
filename=\"" + document.get().getName() + "\"")
.body(new ByteArrayResource(
document.get().getContents()));
}
API 提供了 BodyHandlers 类(HttpResponse 内部静态类)来管理常见的响应类型,例如 String 或 File。以下是此类中可用的一些有用方法的列表:
- ofByteArray:主体写入字节数组。
- ofFile:正文写入文件,HttpResponse.body() 返回对其 Path 的引用。
- ofFileDownload:主体完全写入文件,并且 HttpResponse.body() 返回文件的 Path 对象。
- ofString:正文写入字符串并使用 Content-Type 响应标头中指定的字符集进行解码。
- ofInputStream:返回一个输入流,可以在接收到正文时从中读取正文。
- ofLines:返回一个 Stream。尸体可能还没有收到。
- ofPublisher:返回一个发布者,在接收到正文响应字节时可以从中获取它们。发布者只能而且必须订阅一次。
由于端点返回一个字节数组,因此 ofByteArray 方法似乎是一个很好的匹配。文件名是从 Content-Disposition 标头中提取的。代码片段如下所示:
// Byte Array
HttpResponse<byte[]> response = client
.send(request, HttpResponse.BodyHandlers.ofByteArray());
String headerContentDisposition =
(String)response.headers().firstValue("content-
disposition").get();
String fileName =
"C:/workspace/files/"+getFileName(headerContentDisposition);
// Save to file
Files.write(Paths.get(fileName),
response.body(), StandardOpenOption.CREATE_NEW);
执行程序后,文件将成功下载到指定位置。
Directory: C:\workspace\files
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/1/2023 7:28 PM 388374 LinuxCommands.jpg
可以使用不同的 BodyHandler 来下载文件,如以下几行所示
HttpResponse<Path> response = client.send(request,
HttpResponse.BodyHandlers.ofFile(
Path.of("C:/workspace/files/DownloadedFile.jpg")));
另一种选择是使用 ofInputStream 方法。
HttpResponse<InputStream> response = client
.send(request,
HttpResponse.BodyHandlers.ofInputStream());
String headerContentDisposition =
(String)response.headers().firstValue("content-
disposition").get();
String fileName = "C:/workspace/files/"+
getFileName(headerContentDisposition);
Files.copy(response.body(), Paths.get(fileName),
StandardCopyOption.REPLACE_EXISTING);
正如您所看到的,有很多选择可以完成工作:-)。
上传文件内容
在此用户案例中,已设置两个不同的端点来上传文件。因此,我们将看到不同的方式来使身体发挥作用。
请求正文通过提供给 POST 或 PUT 方法之一的 BodyPublisher 提供。BodyPublishers 类提供了许多常见发布者的实现。以下是 BodyPublishers 中可用的一些方法的列表
- ofString:返回一个 BodyPublisher,其正文是使用 UTF_8 字符转换的给定字符串。
- ofInputStream:从输入流读取数据的主体发布者。
- ofByteArray:返回一个请求主体发布者,其主体是给定的字节数组。
- ofFile:请求主体发布者,从文件内容中获取数据。
- ofByteArrays:请求主体发布者,从字节数组的 Iterable 中获取数据。
现在我们可以继续第一个上传示例。其余端点期望文件内容为字符串。文件类型和名称位于标头中。
@PostMapping()
ResponseEntity<Void> uploadDocument(@RequestBody String data,
@RequestHeader("Content-Type") String type,
@RequestHeader("fileName") String fileName) {
Document document = new Document();
document.setName(fileName);
document.setCreationDate(LocalDate.now());
document.setType(type);
document.setContents(data.getBytes());
documentRepo.save(document);
return ResponseEntity.created(URI.create(
"http://localhost:8080/api/v1/documents/"+document.getId()
)).build();
}
如您所见,BodyPublishers.ofFile 方法采用 Path 作为参数。发送请求时,正文将包含文件的内容。
Path file = Paths.get("C:/workspace/files/trees.jpg");
var request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/api/v1/documents"))
.header("Content-Type", "image/jpg")
.header("fileName", file.getFileName().toString())
.header("Authorization",
getBasicAuthenticationHeader("admin1234","password5678"))
.POST(HttpRequest.BodyPublishers.ofFile(file))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
System.out.printf("Headers %s \n",
response.headers().firstValue("location"));
输出
Status 201
Headers Optional[http://localhost:8080/api/v1/documents/3]
文件被保存到数据库中,并且 URL 会在位置标头中返回以查找它。
在第二个示例中,控制器将主体视为字节数组。
@RestController
@RequestMapping("api/v2/documents")
public class DocumentControllerV2 {
@PostMapping()
ResponseEntity<Void> uploadDocument(@RequestBody byte[] data
,@RequestHeader("Content-Type") String type
,@RequestHeader("fileName") String fileName) {
// omitted code
}
}
ByteArray 方法非常适合这种情况。所需要做的就是将文件的内容转换为字节数组。为此,FileInputStream 将完成这项工作。
String fileName = "C:/workspace/files/java_tutorial.pdf";
var request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost:8080/api/v2/documents"))
.header("Content-Type", "image/png")
.header("filename",
fileName.substring(fileName.lastIndexOf("/")))
.POST(HttpRequest.BodyPublishers.ofByteArray(new
FileInputStream(fileName).readAllBytes()))
.build();
var response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
System.out.printf("Headers %s \n",
response.headers().firstValue("location"));
输出
Status 201
Headers Optional[http://localhost:8080/api/v1/documents/4]
最后,为了验证新文件是否存储在数据库中,将调用列表文件端点。
[
{
"name": "PlainText.txt",
"creationDate": "2023-03-15",
"size": 26,
"type": "text/plain"
},
{
"name": "LinuxCommands.jpg",
"creationDate": "2023-02-07",
"size": 388374,
"type": "image/jpeg"
},
{
"name": "trees.jpg",
"creationDate": "2023-04-02",
"size": 21011905,
"type": "image/jpg"
},
{
"name": "/java_tutorial.pdf",
"creationDate": "2023-04-02",
"size": 1012786,
"type": "image/png"
}
概括
就是这样了。使用 Java 的核心 API 下载和上传文件非常简单。我们必须选择一个合适的正文发布者或正文处理程序来分别发送文件内容和接收文件内容。
关注并回复1即可领取【Java学习资料大礼包】
猜你喜欢
- 2025-01-13 Java开发者必须知道的11 个常用 API 整理
- 2025-01-13 Java SPI 和 API,傻傻分不清?
- 2025-01-13 最新 client-java 调用 k8s ApiServer
- 2025-01-13 Java实现API、服务与客户端代码工程分离
- 2025-01-13 java agent-02-Java Instrumentation API
- 2025-01-13 浅谈Java interface和API的区别
- 2025-01-13 Java 如何设计 API 接口,实现统一格式返回?
- 2025-01-13 【Java版源码】YesApi接口管理系统云服务平台——国产软件推荐
你 发表评论:
欢迎- 04-24Java Collections 工具类集合框架中常用算法解析
- 04-24桶排序的简单理解
- 04-24Java集合框架底层实现原理大揭秘
- 04-24Java 集合框架全面解析:选对数据结构,提升开发效率
- 04-24c#集合排序
- 04-24Java面试中常被问到的集合类深度解读
- 04-24VBA技术资料MF278:对集合进行排序
- 04-24Spring 最常用的 7 大类注解,史上最强整理
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)