| src/main/java/com/zy/asrs/controller/ApkBuildTaskController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/controller/OpenController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/webapp/views/apkBuild/apkBuild.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/zy/asrs/controller/ApkBuildTaskController.java
@@ -1,5 +1,6 @@ package com.zy.asrs.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; @@ -13,6 +14,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -162,6 +170,40 @@ } } @RequestMapping(value = "/apkBuildTask/downloadFile/{id}/auth", method = RequestMethod.GET) @ManagerAuth public void downloadApkFile(@PathVariable("id") Long id, HttpServletResponse response) { try { String localPath = apkBuildTaskService.downloadApk(id); File file = new File(localPath); if (!file.exists()) { throw new RuntimeException("APK文件不存在"); } String fileName = URLEncoder.encode(file.getName(), "UTF-8"); response.setContentType("application/vnd.android.package-archive"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName); response.setHeader("Content-Length", String.valueOf(file.length())); try (InputStream inputStream = new FileInputStream(file); OutputStream outputStream = response.getOutputStream()) { byte[] buffer = new byte[8192]; int len; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.flush(); } } catch (Exception e) { try { response.reset(); response.setCharacterEncoding("utf-8"); response.setContentType("application/json; charset=utf-8"); response.getWriter().print(JSON.toJSONString(R.error("下载APK失败: " + e.getMessage()))); } catch (IOException ignore) { } } } /** * 通过ADB安装APK到指定设备 */ src/main/java/com/zy/asrs/controller/OpenController.java
@@ -133,7 +133,10 @@ list.add(tvDataDto); } return R.ok().add(list); HashMap<String, Object> map = new HashMap<>(); map.put("data", list); map.put("deviceName", tvDevice.getName()); return R.ok().add(map); } @GetMapping("/getError") src/main/webapp/views/apkBuild/apkBuild.html
@@ -224,7 +224,7 @@ <el-table-column label="操作" width="180" align="center" fixed="right"> <template slot-scope="scope"> <el-button type="text" size="small" @click="showDetail(scope.row)">详情</el-button> <el-button type="text" size="small" v-if="scope.row.status === 2 && !scope.row.apkPath" <el-button type="text" size="small" v-if="scope.row.status === 2 && scope.row.apkPath" @click="downloadApk(scope.row)" :loading="scope.row.downloading">下载</el-button> <el-button type="text" size="small" style="color: #67c23a;" v-if="scope.row.status === 2 && scope.row.apkPath" @@ -658,21 +658,58 @@ downloadApk(row) { this.$set(row, 'downloading', true); $.ajax({ url: baseUrl + '/apkBuildTask/download/' + row.id + '/auth', url: baseUrl + '/apkBuildTask/downloadFile/' + row.id + '/auth', headers: this.getHeaders(), method: 'POST', success: (res) => { method: 'GET', xhrFields: { responseType: 'blob' }, success: (data, status, xhr) => { this.$set(row, 'downloading', false); if (res.code === 200) { this.$message.success('APK下载完成: ' + res.data.apkPath); this.loadData(); } else { this.$message.error(res.msg || '下载失败'); const contentType = xhr.getResponseHeader('Content-Type') || ''; if (contentType.indexOf('application/json') !== -1) { const reader = new FileReader(); reader.onload = () => { try { const res = JSON.parse(reader.result); this.$message.error(res.msg || '下载失败'); } catch (e) { this.$message.error('下载失败'); } }; reader.readAsText(data); return; } const disposition = xhr.getResponseHeader('Content-Disposition') || ''; const fileNameMatch = disposition.match(/filename="?([^"]+)"?/); let fileName = fileNameMatch ? decodeURIComponent(fileNameMatch[1]) : ''; if (!fileName) { fileName = (row.projectName ? row.projectName : row.id) + '.apk'; } const blob = new Blob([data], { type: contentType || 'application/octet-stream' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); this.$message.success('APK已开始下载'); }, error: () => { error: (xhr) => { this.$set(row, 'downloading', false); this.$message.error('请求失败'); if (xhr && xhr.response) { const reader = new FileReader(); reader.onload = () => { try { const res = JSON.parse(reader.result); this.$message.error(res.msg || '下载失败'); } catch (e) { this.$message.error('请求失败'); } }; reader.readAsText(xhr.response); } else { this.$message.error('请求失败'); } } }); },