<template>
<view>
<view @click="chooseImage"
style="width: 300rpx;height: 100rpx;display: flex;justify-content: center;align-items: center;border: 1rpx solid red;border-radius: 18rpx;">
上传图片文件</view>
</view>
</template>
<script>
import {
uploadZip
} from '@/api/business/test.js';
import JSZip from 'jszip';
import upload from '@/utils/upload'
export default {
methods: {
chooseImage() {
uni.chooseImage({
count: 1, // 选择一张图片
success: async (res) => {
const tempFilePaths = res.tempFilePaths;
console.log(tempFilePaths);
//压缩并上传
this.compressAndZipImages(tempFilePaths);
}
});
},
compressAndZipImages(filePaths) {
console.log("进入");
const zip = new JSZip();
console.log("new");
const promises = filePaths.map((filePath, index) => {
return new Promise((resolve, reject) => {
//将原图复制到应用私有目录,以便之后读取压缩
uni.saveFile({
tempFilePath: filePath, // 临时文件路径
success(res) {
const savedFilePath = res.savedFilePath; // 保存后的文件路径
plus.io.resolveLocalFileSystemURL(savedFilePath, (entry) => {
console.log("准备读取文件");
console.log("entry", entry);
entry.file((file) => {
console.log("进入entry", file);
const reader = new plus.io.FileReader();
//console.log("reader",reader);
reader.onloadend = (e) => {
console.log("读取文件成功");
const base64 = e.target.result.split(",")[
1]; // 提取 Base64 部分
/* const arrayBuffer = uni.base64ToArrayBuffer(
base64); */ //
const fileName = `image${index + 1}.jpg`; // 文件名
zip.file(file.name, base64, {
base64: true,
compression: "STORE"
});
console.log("添加打包文件");
resolve();
};
reader.onerror = (err) => {
console.log("读取文件失败", err);
reject(err);
};
reader.onprogress = function(event) {
console.log("读取进度:", event.loaded, event.total);
};
reader.readAsDataURL(file);
console.log("reader", reader);
console.log("进入entry结束", reader);
});
}, (err) => {
console.log("准备读取文件失败", err);
reject(err);
});
},
fail(err) {
console.error('文件保存失败:', err);
}
});
/* uni.readFile({
filePath: filePath,
encoding: 'base64', // 以 base64 格式读取
success: (res) => {
const fileName = `image${index + 1}.jpg`; // 文件名
const fileData = atob(res.data); // 将 base64 解码为二进制数据
zip.file(fileName, fileData, {
binary: true
});
console.log("读取文件成功");
resolve();
},
fail: (err) => {
console.log("读取文件失败",err);
reject(err);
}
});*/
});
});
Promise.all(promises).then(() => {
console.log("开始打包");
this.generateZipFile(zip);
}).catch((err) => {
console.error('读取文件失败', err);
});
},
generateZipFile(zip) {
zip.generateAsync({
type: 'base64'
}).then((content) => {
var random = this.generateFourDigitRandomNumber();
//对文件进行压缩
this.writeFileToDoc(random + '.ziptxt', content).then(() => {
//对文件进行上传
uploadZip("file:///storage/emulated/0/Android/data/app.mmwzcloud.com/apps/__UNI__5A0A196/doc/" +
random + '.ziptxt', {
form: JSON.stringify("{aaa:111}")
}).then(res => {
console.log('上传成功', res);
}).catch(err => {
console.log('88888888888', err);
})
/* upload({
url: '/inherit/api/test/uploadZip',
filePath: "file:///storage/emulated/0/Android/data/app.mmwzcloud.com/apps/__UNI__5A0A196/doc/" +
random + '.ziptxt',
formData: {
form: '666'
},
files: []
}).then(res => {
}).catch(err => {
console.log('88888888888', err);
}) */
}).catch((err) => {
console.log('9999999999', err);
});
}).catch((err) => {
console.error('打包失败', err);
});
},
writeFileToDoc(fileName, content) {
return new Promise((resolve, reject) => {
// 解析目标路径
plus.io.resolveLocalFileSystemURL("_doc/", (root) => {
// 创建或获取文件
root.getFile(fileName, {
create: true
}, (fileEntry) => {
// 创建文件写入器
fileEntry.createWriter((writer) => {
writer.onwriteend = () => {
console.log("文件写入成功");
resolve(true);
};
writer.onerror = (err) => {
console.error("写入文件失败:", err);
reject(err);
};
// 写入内容
try {
/* console.log("66",content);
var arr = this.base64ToArrayBuffer(content);
//const arrayBuffer = uni.base64ToArrayBuffer("SGVsbG8gd29ybGQh");
console.log("77",arr);
//const file = new File([arrayBuffer], fileName, { type: "application/zip" });
const dataView = new DataView(arr);
writer.write(dataView); */
//将文本base64写入txt,后端读取转为File,这里没查到怎样直接保存二进制,在安卓平台不支持File,Blob对象
writer.write(content);
} catch (error) {
console.error("神魔杨的错误:", error);
}
}, (err) => {
console.error("创建文件写入器失败:", err);
reject(err);
});
}, (err) => {
console.error("获取文件失败:", err);
reject(err);
});
}, (err) => {
console.error("解析路径失败:", err);
reject(err);
});
});
},
base64ToArrayBuffer(base64Str) { // 去掉 Base64 的 MIME 类型前缀
const binaryString = atob(base64Str);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
},
generateFourDigitRandomNumber() {
return Math.floor(1000 + Math.random() * 9000);
}
}
}
</script>
<style>
</style>
import upload from '@/utils/upload'
import request from '@/utils/request'
export function uploadZip(filePath, formData) {
return upload({
url: '/inherit/api/test/uploadZip',
filePath: filePath,
formData: formData,
files: []
})
}
import store from '@/store'
import config from '@/config'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
let timeout = 10000
const baseUrl = config.baseUrl
const upload = config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
config.header = config.header || {}
if (getToken() && !isToken) {
config.header['Authorization'] = 'Bearer ' + getToken()
}
// get请求映射params参数
if (config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.url = url
}
for(let i = 0; i < config.files.length; i ++) {
if(config.files[i].imageOrVideo == 1 || config.files[i].imageOrVideo == 2) {
config.files[i].name = config.files[i].name + i + 1
}
}
return new Promise((resolve, reject) => {
uni.uploadFile({
timeout: config.timeout || timeout,
url: baseUrl + config.url,
filePath: config.filePath,
name: config.name || 'file',
header: config.header,
formData: config.formData,
files: config.files, // 多文件上传参数
success: (res) => {
let result = JSON.parse(res.data)
const code = result.code || 200
const msg = errorCode[code] || result.msg || errorCode['default']
if (code === 200) {
resolve(result)
} else if (code == 401) {
showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => {
if (res.confirm) {
store.dispatch('LogOut').then(res => {
uni.reLaunch({ url: '/pages/login' })
})
}
})
reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
toast(msg)
reject('500')
} else if (code !== 200) {
toast(msg)
reject(code)
}
},
fail: (error) => {
let { message } = error
if (message == 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
toast(message)
reject(error)
}
})
})
}
export default upload
@PostMapping("/uploadZip")
public AjaxResult uploadZip(HttpServletRequest request, @RequestPart(value = "form") String form){
MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
MultiValueMap<String, MultipartFile> multiFileMap = req.getMultiFileMap();
List<MultipartFile> fileList = new ArrayList<>();
multiFileMap.forEach((key, value) -> {
fileList.addAll(value);
});
MultipartFile[] files = fileList.stream().toArray(MultipartFile[]::new);
List<MultipartFile> list1=new ArrayList<>();
for(MultipartFile multipartFile:files){
String fileName = multipartFile.getOriginalFilename();
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
if (StringUtils.equals(fileExtension,"ziptxt")){
UUID uuid = UUID.randomUUID();
String uuidString = uuid.toString().replace("-", "");
//解压路径
String tempDir = System.getProperty("java.io.tmpdir");
String out=tempDir+uuidString;
System.out.println(out);
UUID uuid1 = UUID.randomUUID();
String uuidString1 = uuid1.toString().replace("-", "");
// 保存文件到指定路径
String fileName1 = multipartFile.getOriginalFilename();
String filePath = tempDir + uuidString1+fileName1;
try {
multipartFile.transferTo(new File(filePath));
} catch (IOException e) {
throw new RuntimeException(e);
}
//读取base64,转为普通文件
String content = FileUtil.readUtf8String(filePath);
byte[] decodedBytes = Base64.getDecoder().decode(content);
//生成zip文件
// 将解码后的字节写入文件
UUID uuid2 = UUID.randomUUID();
String uuidString2 = uuid2.toString().replace("-", "");
try (FileOutputStream fos = new FileOutputStream(tempDir + uuidString2+".zip")) {
fos.write(decodedBytes);
System.out.println("文件写入成功!");
} catch (IOException e) {
System.err.println("写入文件时发生错误:" + e.getMessage());
}
ZipUtil.unzipFile(tempDir + uuidString2+".zip",out);
//读取解压后的所有文件
File directory = new File(out);
if (directory.isDirectory()) {
// 获取目录下的所有文件和子目录
File[] files1 = directory.listFiles();
if (files1 != null) {
for (File file : files1) {
CommonsMultipartFile multipartFile1 = createMultipartFile(file);
list1.add(multipartFile1);
}
}
}
}else{
list1.add(multipartFile);
}
}
MultipartFile[] files1 = list1.stream().toArray(MultipartFile[]::new);
//获取登录用户
LoginAppUser loginAppUser = AppUserContext.getUser();
String string = JSON.toJSON(loginAppUser).toString();
remoteBusImageService.resetBusAndImageByFiles(String.valueOf("666999"), String.valueOf(ModelEnum.ACTIVITY.getModelId()),string,files1,"", SecurityConstants.INNER);
return AjaxResult.success("成功");
}
public CommonsMultipartFile createMultipartFile(File file){
// 创建 FileItem
DiskFileItemFactory factory = new DiskFileItemFactory();
FileItem fileItem = factory.createItem("file", "application/octet-stream", true, file.getName());
// 将文件内容写入 FileItem
try (InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = fileItem.getOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}catch (Exception e){
}
// 创建 CommonsMultipartFile
return new CommonsMultipartFile(fileItem);
}