文章目錄
- 一、背景
- 二、後端實作
- 1、SpringBoot項目API相關結構樹
- 2、檔案上傳工具類的實作
- 3、小程式CRM上傳檔案接口的實作
- 4、小程式CRM上傳檔案接口的檢視
- 三、前端實作
- 1、搭建上傳頁面
- 2、編寫上傳代碼
- 3、上傳測試
一、背景
最近在做一個CRM微信小程式工具,使用者提出了需要通過小程式上傳圖檔、錄音、視訊的需求。針對此需求,本文将通過搭建SpringBoot上傳檔案的API,前端小程式調用後端API,展現微信小程式檔案上傳到SpringBoot的完整案例。
二、後端實作
1、SpringBoot項目API相關結構樹
2、檔案上傳工具類的實作
tools工具類包中主要存檔案通用的檔案上傳工具類,該工具類會将檔案上傳至配置指定的檔案夾下,并将檔案資訊寫入upload_file表中。
- 檔案資訊實體類:與資料庫中表upload_file對應;
- 檔案存儲倉庫類:通過Spring Data JPA接口實作資料的CRUD;
- 檔案上傳工具接口:對外統一封裝檔案上傳方法;
- 檔案上傳工具實作類:實作檔案上傳方法接口。
檔案資訊實體類:UploadFile.java
/**
* 檔案資訊表
*
* @author zhuhuix
* @date 2020-04-20
*/
@Entity
@Getter
@Setter
@Table(name = "upload_file")
public class UploadFile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = Update.class)
private Long id;
/**
* 檔案實際名稱
*/
@Column(name = "real_name")
private String realName;
/**
* 檔案名
*/
@NotNull
@Column(name = "file_name")
private String fileName;
/**
* 檔案主名稱
*/
@NotNull
@Column(name = "primary_name")
private String primaryName;
/**
* 檔案擴充名
*/
@NotNull
private String extension;
/**
* 存放路徑
*/
@NotNull
private String path;
/**
* 檔案類型
*/
private String type;
/**
* 檔案大小
*/
private Long size;
/**
* 上傳人
*/
private String uploader;
@JsonIgnore
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public UploadFile(String realName, @NotNull String fileName, @NotNull String primaryName, @NotNull String extension, @NotNull String path, String type, Long size, String uploader) {
this.realName = realName;
this.fileName = fileName;
this.primaryName = primaryName;
this.extension = extension;
this.path = path;
this.type = type;
this.size = size;
this.uploader = uploader;
}
@Override
public String toString() {
return "UploadFile{" +
"fileName='" + fileName + '\'' +
", uploader='" + uploader + '\'' +
", createTime=" + createTime +
'}';
}
}
檔案存儲倉庫類:UploadFileRepository.java
/**
* 上傳檔案DAO接口層
*
* @author zhuhuix
* @date 2020-04-03
*/
public interface UploadFileRepository extends JpaRepository<UploadFile, Long>, JpaSpecificationExecutor<UploadFile> {
//該接口繼承JpaRepository及CrudRepository接口,已實作了如findById,save,delete等CRUD方法
}
UploadFileRepository 接口繼承JpaRepository及CrudRepository接口,已實作了如findById,save,delete等CRUD方法
檔案上傳工具接口:UploadFileTool.java
/**
* 檔案上傳接口定義
*
* @author zhuhuix
* @date 2020-04-20
*/
public interface UploadFileTool {
/**
* 檔案上傳
* @param multipartFile 檔案
* @return 上傳資訊
*/
UploadFile upload(String uploader,String realName,MultipartFile multipartFile);
}
檔案上傳工具實作類:UploadFileToolImpl.java
/**
* 檔案上傳實作類
*
* @author zhuhuix
* @date 2020-04-20
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UploadFileToolImpl implements UploadFileTool {
private final UploadFileRepository uploadFileRepository;
@Value("${uploadFile.path}")
private String path;
@Value("${uploadFile.maxSize}")
private long maxSize;
public UploadFileToolImpl(UploadFileRepository uploadFileRepository) {
this.uploadFileRepository = uploadFileRepository;
}
@Override
@Transactional(rollbackFor = Exception.class)
public UploadFile upload(String uploader, String realName, MultipartFile multipartFile) {
//檢查檔案大小
if (multipartFile.getSize() > maxSize * Constant.MB) {
throw new RuntimeException("超出檔案上傳大小限制" + maxSize + "MB");
}
//擷取上傳檔案的主檔案名與擴充名
String primaryName = FileUtil.mainName(multipartFile.getOriginalFilename());
String extension = FileUtil.extName(multipartFile.getOriginalFilename());
//根據檔案擴充名得到檔案類型
String type = getFileType(extension);
//給上傳的檔案加上時間戳
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddhhmmssS");
String nowStr = "-" + date.format(format);
String fileName = primaryName + nowStr + "." + extension;
try {
String filePath = path + type + File.separator + fileName;
File dest = new File(filePath).getCanonicalFile();
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
multipartFile.transferTo(dest);
if (ObjectUtil.isNull(dest)) {
throw new RuntimeException("上傳檔案失敗");
}
UploadFile uploadFile = new UploadFile(realName, fileName, primaryName, extension, dest.getPath(), type, multipartFile.getSize(), uploader);
return uploadFileRepository.save(uploadFile);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
/**
* 根據檔案擴充名給檔案類型
*
* @param extension 檔案擴充名
* @return 檔案類型
*/
private static String getFileType(String extension) {
String document = "txt doc pdf ppt pps xlsx xls docx csv";
String music = "mp3 wav wma mpa ram ra aac aif m4a";
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
if (image.contains(extension)) {
return "image";
} else if (document.contains(extension)) {
return "document";
} else if (music.contains(extension)) {
return "music";
} else if (video.contains(extension)) {
return "video";
} else {
return "other";
}
}
}
注意,該程式代碼中用到了@Value注解擷取配置檔案中的uploadFile.path及uploadFile.maxsize參數,一般在項目靜态配置檔案中按如下書寫(yml配置檔案)。
# 測試環境檔案存儲路徑
uploadFile:
path: C:\startup\file\
# 檔案大小 /M
maxSize: 50
3、小程式CRM上傳檔案接口的實作
wx-miniprogram包定義了小程式CRM webApi的接口,小程式調用webApi實作檔案的上傳及其他功能。
- 微信小程式CRM webApi:對外提供小程式上傳檔案webApi;
- 微信小程式CRM服務接口:封裝小程式上傳檔案服務接口;
- 微信小程式CRM服務實作:小程式上傳檔案服務的實作,該服務實作中會調用tools包中的UploadFile接口進行檔案的上傳。
微信小程式CRM webApi:WxMiniCrmController.java
/**
* 微信小程式Crm webApi
*
* @author zhuhuix
* @date 2020-03-30
*/
@Slf4j
@RestController
@RequestMapping("/api/wx-mini")
@Api(tags = "微信小程式Crm接口")
public class WxMiniCrmController {
private final WxMiniCrm wxMiniCrm;
public WxMiniCrmController(WxMiniCrm wxMiniCrm) {
this.wxMiniCrm = wxMiniCrm;
}
@ApiOperation(value = "微信小程式端上傳檔案")
@PostMapping(value = "/fileUpload")
public ResponseEntity fileUpload(HttpServletRequest request) {
MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
MultipartFile multipartFile = req.getFile("file");
String openId = req.getParameter("openId");
String realName = req.getParameter("realName");
String json = req.getParameter("json");
return ResponseEntity.ok(wxMiniCrm.uploadFile(json, openId,realName, multipartFile));
}
}
微信小程式CRM服務接口:WxMiniCrm.java
/**
* 微信小程式CRM服務接口定義
*
* @author zhuhuix
* @date 2020-04-20
*/
public interface WxMiniCrm {
/**
* 将微信小程式傳入的json對象寫入資料庫,并同時将檔案上傳至服務端
*
* @param json 微信端傳入json對象
* @param openId 上傳人
* @param realName 檔案實際名稱
* @param multipartFile 上傳檔案
* @return 傳回上傳資訊
*/
Result<UploadFile> uploadFile(String json, String openId, String realName,MultipartFile multipartFile);
}
微信小程式CRM服務實作:WxMiniCrmImpl.java
/**
* 微信小程式CRM實作類
*
* @author zhuhuix
* @date 2020-04-20
*/
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class WxMiniCrmImpl implements WxMiniCrm {
private final UploadFileTool uploadFileTool;
public WxMiniCrmImpl(UploadFileTool uploadFileTool) {
this.uploadFileTool = uploadFileTool;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result<UploadFile> uploadFile(String json, String openId,String realName, MultipartFile multipartFile) {
return new Result<UploadFile>().ok(uploadFileTool.upload(openId,realName, multipartFile));
}
}
4、小程式CRM上傳檔案接口的檢視
通路Swagger2可檢視該接口,Swagger2與SpringBoot的內建可參考SpringBoot JWT認證機制項目內建Swagger2
三、前端實作
1、搭建上傳頁面
上傳頁面中用到了 有贊vant-weapp Uploader 檔案上傳元件
<view style="margin-top: 30rpx;">
<van-cell-group>
<van-field
value="{{ userName }}"
label="名稱"
placeholder="請輸入稱呼"
right-icon="contact"
bind:input="onUserNameInput"
/>
<van-field
value="{{ phone }}"
type="number"
label="聯系方式"
placeholder=""
right-icon="phone-o"
bind:input="onPhoneInput"
/>
<van-field
value="{{ company }}"
label="機關"
placeholder="請輸入機關名稱"
right-icon="cluster-o"
bind:input="onCompanyInput"
/>
</van-cell-group>
</view>
<van-cell-group title="個人資訊">
<van-uploader style="margin-left: 5rpx; padding: 0 20rpx;"
file-list="{{ idCardFront }}"
max-count="{{ 3 }}"
multiple
accept="all"
max-size= "52428800"
bind:before-read="beforeReadIdCardFront"
bind:after-read="afterReadIdCardFront"
bind:delete="deleteIdCardFront"
bind:click-preview="clickPreviewCardImage"
/>
</van-cell-group>
2、編寫上傳代碼
該代碼中調用wx.uploadFile API接口
/**上傳檔案 */
uploadUserCards: function(cards, realName) {
let uploadCards = cards;
let uploadRealName = realName;
uploadCards.forEach(element => {
console.log("element", element);
if (typeof element.openId == "undefined") {
wx.uploadFile({
url: api.wxFileUploadUrl,
filePath: element.path,
name: "file",
header: {
"Authorization": wx.getStorageSync("loginFlag"),
"Content-Type": "multipart/form-data"
},
formData: {
openId: app.globalData.userInfo.openId,
realName:realName,
json: JSON.stringify({"fileName":realName})
},
success: result => {
console.log("success:",result);
if (result.statusCode == "200") {
let data = JSON.parse(result.data);
console.log("data", data);
if (data.success == true) {
let module = data.module;
console.log("module", module);
let card = {
openId: app.globalData.userInfo.openId,
cardKey: app.globalData.userInfo.openId,
url:
api.baseUrl + "file/" + module.type + "/" + module.fileName,
name: uploadPictureName,
isImage: module.type=="image"? true:false
};
} else {
app.showInfo("異常錯誤" + data.errMsg + ",請重新進入");
}
} else {
app.showInfo("登入逾時,傳回上一頁,請重新進入");
}
},
fail: result => {
console.log("fail",result);
}
});
}
});
},
3、上傳測試
上傳一張圖檔:
服務端檔案存儲: