[版权申明] 非商业目的注明出处可自由转载
出自:shusheng007
前两天遇到一个需要将Base64转换为MultipartFile的需求,于是网上搜索了一下,千篇一律的都是同一篇从国外网站搬运过来的那一篇文章,然后没有任何解释,没有任何改动,里面很多需要改进的地方也没有说,就是一顿猛抄。哎,国内IT与国外确实还有较大的差距,国人还需要努力,首先态度上就应该改变。
鉴于此,我准备简单整理一下这块,力争使我们后辈既知其然,也知其所以然!后浪加油浪,要狂狼!
真的是一顿猛抄,你抄我我抄你,你在搜索引擎上搜索BASE64DecodedMultipartFile
就能看见国人抄的都是同一篇文章了。你看下面的使用方式也是一顿猛抄,也不管为什么这么写,这么写对不对。还有人提问:base64解码后的byte[]
数组什么要加256啊?看看把我们祖国的下一代IT工作者困惑成了啥样?
String[] baseStrs = base64.split(",");
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = new byte[0];
b = decoder.decodeBuffer(baseStrs[1]);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
return new BASE64DecodedMultipartFile(b, baseStrs[0]);
我初次看到网上BASE64DecodedMultipartFile
类及其使用方式感觉到莫名其妙,主要是因为其是依据带DataURI的Base64字符串写的,要是你获得是纯base64数据,相信你已经懵逼了。
那个使用方式也值得商榷,当从base64解码成byte[]
后,却要循环检查是否包含负值然后加256也是莫名其妙。解码后的byte[]
数组已经是Base64代表的具体内容(图片,文字…)的二进制表示形式了,直接使用即可不知道为什么还要变换。
此处原来有误,感谢评论区小伙伴提醒
BASE64Decoder
明确被Java官方标记为不推荐使用,将来可能被删除或修改,也没人管。
我想了一下还是写一篇文章吧,也算是为纠正这个话题的一点努力,希望有缘人看一看到,修正这个base64转MultipartFile在中国互联网上的流毒。
由于MultipartFile
是一个接口,而Java类库没有提供一个将Base64转换为MultipartFile
的合适的实现类,所以我们需要自己实现这个接口。实现过程中有几点需要注意。
首先确定你要处理的base64数据是否携带DataURI, 像下面这样
data:image/jpeg;base64,/9j/4AA...
如果带我们就可以从其中获得文件的contentType,文件扩展名等。
getOriginalFilename()
方法最好带上文件的扩展名,例如你的是图片的话,带上.jpg .png
之类的。getContentType()
方法返回其内容类型,例如image/png
下面是我改进的一个实现类
/**
* Created by ShuSheng007
* <p>
* author : ShuShneg007
* date : 2021/6/25 19:09
* description:
*/
public class Base64ToMultipartFile implements MultipartFile {
private final byte[] fileContent;
private final String extension;
private final String contentType;
/**
* @param base64
* @param dataUri 格式类似于: data:image/png;base64
*/
public Base64ToMultipartFile(String base64, String dataUri) {
this.fileContent = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8));
this.extension = dataUri.split(";")[0].split("/")[1];
this.contentType = dataUri.split(";")[0].split(":")[1];
}
public Base64ToMultipartFile(String base64, String extension, String contentType) {
this.fileContent = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8));
this.extension = extension;
this.contentType = contentType;
}
@Override
public String getName() {
return "param_" + System.currentTimeMillis();
}
@Override
public String getOriginalFilename() {
return "file_" + System.currentTimeMillis() + "." + extension;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return fileContent == null || fileContent.length == 0;
}
@Override
public long getSize() {
return fileContent.length;
}
@Override
public byte[] getBytes() throws IOException {
return fileContent;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(fileContent);
}
@Override
public void transferTo(File file) throws IOException, IllegalStateException {
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(fileContent);
}
}
}
唯一需要注意的是,如果你要转换的base64是不带DataURI的,那你有两个选择,
dataUri
,如下面代码所示。
public Boolean uploadFile(String base64) {
final String[] base64Array = base64.split(",");
String dataUir, data;
if (base64Array.length > 1) {
dataUir = base64Array[0];
data = base64Array[1];
} else {
//根据你base64代表的具体文件构建
dataUir = "data:image/jpg;base64";
data = base64Array[0];
}
MultipartFile multipartFile = new Base64ToMultipartFile(data, dataUir);
...
return true;
}
Base64ToMultipartFile(String base64, String extension, String contentType)
以上就是全部内容,希望可以对需要的人有所帮助,凡事多挖一点,你就会比别人更牛一点。
关于Base64算法的文章推荐阅读 让你彻底理解Base64算法(Base64是什么,Base64解决什么问题,Base64字符串末尾的=是什么)
又到了点赞支持的时候了,这篇文章的意义我觉得与其他文章不同,大家多支持,让我们一起扭转网上那些错误的抄袭文章,早点回家抱孩子,陪老婆…
一如既往,你可以在GitHub上找到本文的源码:Base64ToMultipartFile