[add] file upload docs
This commit is contained in:
parent
3f3fe5221c
commit
f5893c6ec2
99
docs/api doc/附件上传接口.md
Normal file
99
docs/api doc/附件上传接口.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
## 1. 附件上传
|
||||||
|
|
||||||
|
### 1.1 接口描述
|
||||||
|
上传图片、视频、压缩文件等。
|
||||||
|
### 1.2 请求URL
|
||||||
|
`/v1/post`
|
||||||
|
|
||||||
|
### 1.3 请求方式
|
||||||
|
**POST**
|
||||||
|
|
||||||
|
multipart/form-data方式上传文件
|
||||||
|
|
||||||
|
### 1.4 请求头示例
|
||||||
|
```http
|
||||||
|
Content-Type: multipart/form-data; boundary=----12256474795412178794287418104
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.6 请求体示例
|
||||||
|
```http
|
||||||
|
-----------------------------12256474795412178794287418104
|
||||||
|
Content-Disposition: form-data; name="type"
|
||||||
|
|
||||||
|
public/image
|
||||||
|
-----------------------------12256474795412178794287418104
|
||||||
|
Content-Disposition: form-data; name="file"; filename="2024-03-18_22-06.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
这里是文件内容...
|
||||||
|
-----------------------------12256474795412178794287418104
|
||||||
|
|
||||||
|
```
|
||||||
|
```http
|
||||||
|
-----------------------------35576727471291609851653063070
|
||||||
|
Content-Disposition: form-data; name="type"
|
||||||
|
attachment
|
||||||
|
-----------------------------35576727471291609851653063070
|
||||||
|
Content-Disposition: form-data; name="file"; filename="paopao.zip"
|
||||||
|
Content-Type: application/zip
|
||||||
|
这里是文件内容...
|
||||||
|
-----------------------------35576727471291609851653063070
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.7 返回参数说明
|
||||||
|
| 参数名称 | 必填 | 数据类型 | 约束条件 | 描述 |
|
||||||
|
|------| ---- | -------- | -- |-----------|
|
||||||
|
| code | 是 | 整型 | | 错误码,0表示成功 |
|
||||||
|
| msg | 否 | 字符串 | | 错误信息描述 |
|
||||||
|
| data | 否 | json | | 具体业务数据 |
|
||||||
|
|
||||||
|
|
||||||
|
data结构说明:
|
||||||
|
|
||||||
|
| 参数名称 | 必填 | 数据类型 | 约束条件 | 描述 |
|
||||||
|
|-------| ---- | -------- |------|-----------|
|
||||||
|
| | | | | |
|
||||||
|
|
||||||
|
### 1.8 响应示例(成功)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"user_id": 100066,
|
||||||
|
"file_size": 249763,
|
||||||
|
"img_width": 0,
|
||||||
|
"img_height": 0,
|
||||||
|
"type": 1,
|
||||||
|
"content": "http://60.204.241.255:8008/oss/paopao/public/image/4f/77/ec/5f/85ad-4189-887d-785cac178e21.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 1.9 响应示例(错误)
|
||||||
|
```json
|
||||||
|
{ "code": 500, "msg": "失败" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.10 错误响应码参考
|
||||||
|
更多响应错误码及含义,请参阅[API响应码表](URL/for/api/responseCode/table)。
|
||||||
|
|
||||||
|
### 1.11 安全性与认证
|
||||||
|
|
||||||
|
|
||||||
|
### 1.12 测试环境
|
||||||
|
访问测试环境以进行接口调试:
|
||||||
|
[https://test.apiAddress.com](https://test.apiAddress.com)
|
||||||
|
|
||||||
|
### 1.13 版本管理
|
||||||
|
本API通过URI路径进行版本控制。请在请求URL中包含`/v1`以使用当前版本。
|
||||||
|
|
||||||
|
### 1.14 更新记录
|
||||||
|
- **2024-04-29**:发布文档初始版本。
|
||||||
|
|
||||||
|
|
||||||
|
### 1.15 联系支持
|
||||||
|
如需帮助或对API有任何疑问,请通过电子邮件与我们联系:[support@api.com](mailto:support@api.com)。
|
||||||
|
|
||||||
|
### 1.16 反馈与建议
|
||||||
|
发现文档问题或有改进建议?请填写[反馈表单](https://forms.api.com/feedback)与我们分享。
|
||||||
|
|
46
docs/guides/form-data.md
Normal file
46
docs/guides/form-data.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
## multipart/form-data
|
||||||
|
|
||||||
|
`multipart/form-data` 是一种在HTTP请求中用于上传文件和提交表单数据的编码类型。它主要用于POST请求,允许在同一个请求中发送多个不同类型的数据部分,比如文本字段、文件、二进制数据等。这种格式特别适合于文件上传场景,因为它可以处理大体积数据,并且能够维持数据的边界和类型区分。以下是关于`multipart/form-data`的一些关键点介绍:
|
||||||
|
|
||||||
|
### 基本概念
|
||||||
|
|
||||||
|
- **多部分**: 表示请求体由多个部分组成,每个部分对应表单中的一个字段或一个文件。
|
||||||
|
- **边界**: `multipart/form-data`请求体中,各部分之间由特定的边界字符串分隔。这个边界字符串是唯一的,通常由客户端生成并在Content-Type头中声明,以确保服务器能够正确解析各个部分。
|
||||||
|
|
||||||
|
### 使用场景
|
||||||
|
|
||||||
|
- **文件上传**: 当需要通过表单上传文件时,必须使用`multipart/form-data`。这是因为普通的表单编码(如`application/x-www-form-urlencoded`)不支持二进制数据。
|
||||||
|
- **大体积或复杂数据**: 对于包含大量文本或需要保持数据原始格式(如富文本编辑器的内容)的情况,使用`multipart/form-data`也是合适的。
|
||||||
|
|
||||||
|
### 请求示例
|
||||||
|
|
||||||
|
一个典型的`multipart/form-data`请求看起来像这样(简化版,实际请求会包含更多HTTP头部信息):
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /upload HTTP/1.1
|
||||||
|
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
Content-Disposition: form-data; name="text"
|
||||||
|
|
||||||
|
Hello, World!
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW
|
||||||
|
Content-Disposition: form-data; name="file"; filename="example.txt"
|
||||||
|
Content-Type: text/plain
|
||||||
|
|
||||||
|
This is an example file content.
|
||||||
|
------WebKitFormBoundary7MA4YWxkTrZu0gW--
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关键部分说明
|
||||||
|
|
||||||
|
- **Content-Type**: 包含了`boundary`参数,定义了分隔各个部分的边界字符串。
|
||||||
|
- **Content-Disposition**: 指定了该部分的名称(如果是表单字段)或文件名(如果是文件上传),以及它是表单数据的一部分还是文件。
|
||||||
|
- **实际数据**: 在每个部分的头部信息之后,紧接着就是该部分的实际内容,可以是文本、图片、视频等任何形式的数据。
|
||||||
|
|
||||||
|
### 处理`multipart/form-data`
|
||||||
|
|
||||||
|
服务器端处理这类请求时,需要解析请求体,识别出各个部分,并根据Content-Disposition头部确定每个部分的类型和处理方式。大多数现代Web框架(如Spring Boot、Django、Express.js等)都提供了内置的支持来简化这一过程。
|
||||||
|
|
||||||
|
总之,`multipart/form-data`是一种在HTTP请求中携带复杂数据(特别是文件)的标准格式,广泛应用于Web表单提交和API接口设计中。
|
397
docs/tasks/任务9-Sprint-2- 文件上传.md
Normal file
397
docs/tasks/任务9-Sprint-2- 文件上传.md
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
## 任务名称: 文件上传
|
||||||
|
### 目标:
|
||||||
|
- 掌握框架中文件上传的实现
|
||||||
|
- 了解MapStruct的自定义映射
|
||||||
|
-
|
||||||
|
### 预备知识:
|
||||||
|
- [multipart/form-data](../guides/form-data.md)
|
||||||
|
|
||||||
|
|
||||||
|
### 操作步骤
|
||||||
|
|
||||||
|
对于文件上传,服务器端需要做:
|
||||||
|
- **文件上传的接收**
|
||||||
|
- **文件存储**
|
||||||
|
|
||||||
|
存储方案有: 文件系统、云存储(如Amazon S3、阿里云OSS)、数据库(对于小文件)等。
|
||||||
|
|
||||||
|
本实现使用文件系统存储。
|
||||||
|
|
||||||
|
#### 1. 撰写附件上传接口的API文档
|
||||||
|
|
||||||
|
|
||||||
|
#### 2. 上传相关的自定义配置
|
||||||
|
|
||||||
|
在`application.yml`中添加以下配置:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
app:
|
||||||
|
upload:
|
||||||
|
path: /home/whz/tmp/upload # 文件上传的存储路径
|
||||||
|
sub-path-name-length: 2 # 子路径名称的长度
|
||||||
|
base-url: http://localhost:8080/upload # 文件访问的URL
|
||||||
|
```
|
||||||
|
|
||||||
|
实现一个对应的配置类,目的是为了后续的AttachmentMapper中获取配置:
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.conf;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "app.upload")
|
||||||
|
public class AppUploadProperties {
|
||||||
|
String baseUrl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 数据结构
|
||||||
|
|
||||||
|
**实现附件上传的实体类Attachment**
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
|
import org.hibernate.annotations.Comment;
|
||||||
|
import org.springframework.data.annotation.CreatedDate;
|
||||||
|
import org.springframework.data.annotation.LastModifiedDate;
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Comment("附件")
|
||||||
|
@Entity
|
||||||
|
@Table(name = "p_attachment", indexes = {
|
||||||
|
@Index(name = "idx_attachment_user", columnList = "user_id")
|
||||||
|
})
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
public class Attachment {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "file_size", nullable = false)
|
||||||
|
private Long fileSize = 0L;
|
||||||
|
|
||||||
|
@ColumnDefault("0")
|
||||||
|
@Column(name = "img_width", nullable = false)
|
||||||
|
private Integer imgWidth = 0;
|
||||||
|
|
||||||
|
@ColumnDefault("0")
|
||||||
|
@Column(name = "img_height", nullable = false)
|
||||||
|
private Integer imgHeight = 0;
|
||||||
|
|
||||||
|
@Comment("1图片,2视频,3其他附件")
|
||||||
|
@Column(name = "type", nullable = false)
|
||||||
|
private Byte type = 1;
|
||||||
|
|
||||||
|
@Column(name = "content", nullable = false)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@Comment("创建时间")
|
||||||
|
@CreatedDate
|
||||||
|
@Column(name = "created_on", nullable = false)
|
||||||
|
private Long createdOn;
|
||||||
|
|
||||||
|
@Comment("修改时间")
|
||||||
|
@LastModifiedDate
|
||||||
|
@Column(name = "modified_on", nullable = false)
|
||||||
|
private Long modifiedOn;
|
||||||
|
|
||||||
|
@Comment("删除时间")
|
||||||
|
@Column()
|
||||||
|
private Long deletedOn = 0L;
|
||||||
|
|
||||||
|
@Comment("是否删除 0 为未删除、1 为已删除")
|
||||||
|
@Column(name = "is_del", nullable = false)
|
||||||
|
private byte isDel = 0;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "user_id")
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**实现对应的DTO类AttachmentDo**
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.dto;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
public class AttachmentDto implements Serializable {
|
||||||
|
Long id;
|
||||||
|
Long fileSize;
|
||||||
|
Integer imgWidth;
|
||||||
|
Integer imgHeight;
|
||||||
|
Byte type;
|
||||||
|
String content;
|
||||||
|
Long createdOn;
|
||||||
|
Long userId;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**实现对应的MapStruct映射**
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.mapper;
|
||||||
|
|
||||||
|
import com.lk.paopao.conf.AppUploadProperties;
|
||||||
|
import com.lk.paopao.dto.AttachmentDto;
|
||||||
|
import com.lk.paopao.entity.Attachment;
|
||||||
|
import org.mapstruct.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
||||||
|
public abstract class AttachmentMapper {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
AppUploadProperties appUploadProperties ;
|
||||||
|
|
||||||
|
@Mapping(source = "user.id", target = "userId")
|
||||||
|
@Mapping(target = "content", expression = "java(addHttpPrefix(attachment.getContent()))")
|
||||||
|
public abstract AttachmentDto toDto(Attachment attachment);
|
||||||
|
|
||||||
|
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||||
|
public abstract Attachment partialUpdate(AttachmentDto attachmentDto, @MappingTarget Attachment attachment);
|
||||||
|
|
||||||
|
String addHttpPrefix(String content) {
|
||||||
|
if (content != null && !content.startsWith("http://") && !content.startsWith("https://")) {
|
||||||
|
// 添加HTTP前缀并去掉"//"
|
||||||
|
return appUploadProperties.getBaseUrl() + content;
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**注意**:
|
||||||
|
- `addHttpPrefix` 方法用于将上传的文件路径转换为完整的URL。
|
||||||
|
- 使用了抽象类`AttachmentMapper`,目的是能够使用`@Autowired`注解注入`AppUploadProperties`对象。
|
||||||
|
- @Mapping 注解用于指定映射规则。
|
||||||
|
- `@BeanMapping` 注解用于指定部分属性的更新策略。
|
||||||
|
|
||||||
|
#### 4. 创建JPA接口 AttachmentRepository
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.repository;
|
||||||
|
|
||||||
|
import com.lk.paopao.entity.Attachment;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface AttachmentRepository extends JpaRepository<Attachment, Long> {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### 5. 创建对应的Service类AttachService
|
||||||
|
|
||||||
|
AttachService完成附件上传的业务逻辑。
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.service;
|
||||||
|
|
||||||
|
import com.lk.paopao.dto.AttachmentDto;
|
||||||
|
import com.lk.paopao.entity.Attachment;
|
||||||
|
import com.lk.paopao.entity.User;
|
||||||
|
import com.lk.paopao.mapper.AttachmentMapper;
|
||||||
|
import com.lk.paopao.repository.AttachmentRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AttachService {
|
||||||
|
|
||||||
|
// 从配置中获取上传路径
|
||||||
|
@Value("${app.upload.path}")
|
||||||
|
String UPLOAD_DIR;
|
||||||
|
|
||||||
|
// 从配置中获取子路径名长度,用于文件分目录存储
|
||||||
|
@Value("${app.upload.sub-path-name-length}")
|
||||||
|
int SUB_PATH_LENGTH = 1;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
AuthService authService;
|
||||||
|
@Autowired
|
||||||
|
AttachmentRepository attachmentRepository;
|
||||||
|
@Autowired
|
||||||
|
AttachmentMapper attachmentMapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传附件
|
||||||
|
* @param file 文件
|
||||||
|
* @return AttachmentDto
|
||||||
|
* @throws IOException 输入输出异常
|
||||||
|
*/
|
||||||
|
public AttachmentDto upload(MultipartFile file) throws IOException {
|
||||||
|
// 获取原始文件名
|
||||||
|
String originFileName = file.getOriginalFilename();
|
||||||
|
if(originFileName == null){
|
||||||
|
throw new IllegalArgumentException("没有原始文件名");
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream inputStream = file.getInputStream();
|
||||||
|
// 获取当前用户
|
||||||
|
User currentUser = authService.getCurrentUser();
|
||||||
|
// 上传文件并获取相对URL
|
||||||
|
String relativeUrl = save(originFileName,inputStream);
|
||||||
|
Attachment attachment = new Attachment();
|
||||||
|
// 设置附件类型
|
||||||
|
attachment.setType(getType(file.getContentType()));
|
||||||
|
// 设置附件内容(即存储的URL)
|
||||||
|
attachment.setContent(relativeUrl);
|
||||||
|
// 关联用户
|
||||||
|
attachment.setUser(currentUser);
|
||||||
|
// 设置文件大小
|
||||||
|
attachment.setFileSize(file.getSize());
|
||||||
|
// 保存附件
|
||||||
|
Attachment savedAttachment = attachmentRepository.save(attachment);
|
||||||
|
// 转换并返回附件DTO
|
||||||
|
return attachmentMapper.toDto(savedAttachment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文件到上传目录中
|
||||||
|
* @param fileName 原文件名
|
||||||
|
* @param fileStream 文件流
|
||||||
|
* @return 保存后的文件访问路径
|
||||||
|
* @throws IOException 文件操作异常
|
||||||
|
*/
|
||||||
|
public String save(String fileName, InputStream fileStream) throws IOException {
|
||||||
|
// 生成新的文件名以避免重复
|
||||||
|
String rename = UUID.randomUUID().toString();
|
||||||
|
int dotIndex = fileName.lastIndexOf('.');
|
||||||
|
// 新文件名,包含扩展名
|
||||||
|
String newFile = rename+((dotIndex > 0) ? "."+fileName.substring(dotIndex + 1) : "");
|
||||||
|
|
||||||
|
// 根据子路径长度计算文件保存的子目录
|
||||||
|
String subPath = rename.substring(0,SUB_PATH_LENGTH);
|
||||||
|
// 完整的保存路径
|
||||||
|
String uploadPath = UPLOAD_DIR+"/"+subPath;
|
||||||
|
|
||||||
|
// 确保目录存在,不存在则创建
|
||||||
|
Path directory = Paths.get(uploadPath);
|
||||||
|
if (!Files.exists(directory)) {
|
||||||
|
Files.createDirectories(directory);
|
||||||
|
}
|
||||||
|
// 文件的最终保存位置
|
||||||
|
Path targetLocation = Paths.get(uploadPath, newFile);
|
||||||
|
// 复制文件流到目标位置
|
||||||
|
Files.copy(fileStream, targetLocation);
|
||||||
|
// 返回文件的访问路径
|
||||||
|
return "/"+subPath+"/"+newFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件的MIME类型返回文件类型标识
|
||||||
|
* @param contentType 文件的MIME类型
|
||||||
|
* @return 文件类型的标识字节,0表示未知类型
|
||||||
|
*/
|
||||||
|
public static byte getType(String contentType) {
|
||||||
|
// 存储MIME类型与文件类型标识的映射
|
||||||
|
Map<String,Byte> map = new HashMap<>();
|
||||||
|
|
||||||
|
// 初始化映射,定义各类文件的类型标识
|
||||||
|
map.put("image/jpeg", (byte)1);
|
||||||
|
map.put("image/png", (byte)1);
|
||||||
|
map.put("image/gif", (byte)1);
|
||||||
|
map.put("image/bmp", (byte)1);
|
||||||
|
map.put("image/webp", (byte)1);
|
||||||
|
map.put("image/svg+xml", (byte)1);
|
||||||
|
map.put("image/tiff", (byte)1);
|
||||||
|
map.put("image/x-icon", (byte)1);
|
||||||
|
map.put("image/vnd.microsoft.icon", (byte)1);
|
||||||
|
map.put("video/mp4", (byte)2);
|
||||||
|
map.put("video/x-msvideo", (byte)2);
|
||||||
|
map.put("video/x-ms-wmv", (byte)2);
|
||||||
|
map.put("video/x-flv", (byte)2);
|
||||||
|
map.put("video/quicktime", (byte)2);
|
||||||
|
map.put("video/x-matroska", (byte)2);
|
||||||
|
map.put("video/webm", (byte)2);
|
||||||
|
map.put("video/ogg", (byte)2);
|
||||||
|
map.put("application/zip", (byte)3);
|
||||||
|
map.put("application/x-7z-compressed", (byte)3);
|
||||||
|
map.put("application/x-rar-compressed", (byte)3);
|
||||||
|
map.put("application/x-tar", (byte)3);
|
||||||
|
map.put("application/x-gzip", (byte)3);
|
||||||
|
map.put("application/x-bzip2", (byte)3);
|
||||||
|
map.put("application/x-xz", (byte)3);
|
||||||
|
map.put("application/pdf", (byte)4);
|
||||||
|
map.put("application/msword", (byte)4);
|
||||||
|
// 获取文件类型标识
|
||||||
|
Byte type = map.get(contentType);
|
||||||
|
//获取不到type,则返回0
|
||||||
|
return type==null?0:type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### 6. 创建控制器AttachmentController
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.lk.paopao.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.lk.paopao.dto.AttachmentDto;
|
||||||
|
import com.lk.paopao.dto.rest.response.DataResult;
|
||||||
|
import com.lk.paopao.dto.rest.response.ResultUtil;
|
||||||
|
import com.lk.paopao.service.AttachService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("${app.version}/attachment")
|
||||||
|
public class AttachmentController {
|
||||||
|
@Autowired
|
||||||
|
AttachService attachService;
|
||||||
|
|
||||||
|
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
|
public DataResult<AttachmentDto> upload(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
|
|
||||||
|
AttachmentDto dto = attachService.upload(file);
|
||||||
|
return ResultUtil.ok(dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
说明:
|
||||||
|
- @RequestParam("file"): 表示请求参数中的文件
|
||||||
|
|
||||||
|
### 技术/工具需求:
|
||||||
|
- [列出完成任务所需的技术栈、工具、软件版本等。]
|
||||||
|
|
||||||
|
### 成功标准:
|
||||||
|
- [明确完成任务的评判标准,如代码功能实现、性能指标、测试通过条件等。]
|
||||||
|
|
||||||
|
### 扩展学习(可选):
|
||||||
|
- [提供一些额外学习资源或挑战性任务,鼓励学有余力的学生进一步探索。]
|
||||||
|
|
||||||
|
### 评估与反馈:
|
||||||
|
- [说明如何提交作业、代码审查的标准、或任何反馈收集机制。]
|
||||||
|
|
||||||
|
### 时间估算:
|
||||||
|
- [给出预计完成该任务所需的时间,帮助学生合理安排学习计划。]
|
Loading…
Reference in New Issue
Block a user