1. 前言:
picgo插件的简单开发
上篇文章我们简单写了picgo上传插件,但是当我们测试的时候,发现问题了,后端MultipartFile file
接受到的文件为null。
2. 排查问题:
参考的文档
- picgo api列表
- 关于multipart form-data中filename的问题
2.1. 我们先排查前端
const handle = async (ctx) => {
let userConfig = ctx.getConfig('picBed.haowan-uploader')
if (!userConfig) {
throw new Error('Can\'t find uploader config')
}
const Url = userConfig.Url
const Token = userConfig.Token
const imgList = ctx.output
for (let i in imgList) {
let image = imgList[i].buffer
if (!image && imgList[i].base64Image) {
image = Buffer.from(imgList[i].base64Image, 'base64')
}
const postConfig = postOptions(Url, Token, imgList[i].fileName, image)
let body = await ctx.request(postConfig)
body = JSON.parse(body)
return ctx
}
const postOptions = (Url, Token, fileName, image) => {
return {
method: 'POST',
url: Url + `/api/picgo/upload`,
headers: {
"contentType": 'multipart/form-data',
'Authorization': Token,
'User-Agent': 'PicGo'
},
formData: {
file : image,
fileName
}
}
}
- 我首先考虑的是我api使用问题
🌴我使用的是pico的.request
方法,作者描述是通过使用axios实现的。
🌴使用formdata属性配置表单数据是没有问题的,可以看到picgo的底层通过读取formdata属性,把你所配置的数据读取配置到axios发送的data数据中。是axios的常用实现。
😄 由于我们使用的是picgo gui,所以控制台无法方便的使用,所以我们下面从后端排查数据是否发送
2.2. 排查后端
-
在参数接收这里点上debug
🌴我们可以看出并非没有接受文件,只是在最后并没有转换成文件。
-
查看body流读取的源码
Collection<Part> parts = request.getParts();
this.multipartParameterNames = new LinkedHashSet(parts.size());
MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap(parts.size());
Iterator var4 = parts.iterator();
while(var4.hasNext()) {
Part part = (Part)var4.next();
String headerValue = part.getHeader("Content-Disposition");
ContentDisposition disposition = ContentDisposition.parse(headerValue);
String filename = disposition.getFilename();
if (filename != null) {
if (filename.startsWith("=?") && filename.endsWith("?=")) {
filename = StandardMultipartHttpServletRequest.MimeDelegate.decode(filename);
}
files.add(part.getName(), new StandardMultipartFile(part, filename));
} else {
this.multipartParameterNames.add(part.getName());
}
}
this.setMultipartFiles(files);
String filename = disposition.getFilename();
,由于这里文件名为空,以致于mvc根本不处理文件流。
那么解决方案就显而易见,给添加上文件流就行。
3. 解决方案(添加文件名):
- https://www.rfc-editor.org/rfc/rfc1867 (formdata上传文件描述)
2. formdata buffer流添加文件名
formData: {
file: {
value: image,
options: {
filename: fileName
}
}
可以在formdata中可选属性options添加文件名的选项。就可以成功读取了。