@
目錄
- 1.報錯如圖
- 2.專案背景
- 3.網上的解決方案
- 4.我的最終解決方案
1.報錯如圖
2.專案背景
我們的專案採用的全是https請求,而使用第三方檔案管理器go-fastdfs,該檔案管理器返回的所有下載檔案的請求全是http開頭的,比如http://10.110.38.253:11014/group1/batchImportData/組 (26).xlsx,然而在https請求下使用http的請求就會報如上圖的錯誤,且不能把檔案下載請求http改為https,因為修改後會查詢不到檔案。所以必須只能採用http的請求且想讓功能實現。
注意點1:
我們公司專案請求協議字首必須是https的,執行http的無效
注意點2:
這種第三方返回的檔案下載路徑http://10.110.38.253:11014/group1/batchImportData/組 (26).xlsx,是可以直接放在瀏覽器上直接下載的,具體請看如圖
3.網上的解決方案
可以先看下其他人的部落格,但是方案對我目前公司專案無效
1.https頁面載入http資源的解決方法
2.分享 4個解決 https頁面載入http資源報錯的方法
問題:裡面的方案為啥對我公司的專案無效?
答案:
- 針對修改協議字首的方案,我們的必須得是https的才行,其他無效。
- 針對使用 iframe 的方案,因為沒用過,且感覺專案引入會很費事且龐雜,所以當時沒考慮該方案。
- 針對自動升級方案(也就是說把第三方檔案管理器go-fastdfs配置檔案改了,由http協議改為https協議),該方案真對我的專案不行,因為我的公司有很多老專案都是用這個檔案管理器go-fastdfs,如果把協議改了,不清楚對其他服務會不會有影響,所以輕易不能動。
綜上所述:
上面的方案我一個都不能用,所以我需要另想他法。
4.我的最終解決方案
接下來說下我最終想到的方便且容易上手的解決方案:那就是採用http工具執行url -> 然後把檔案先下載到專案所在伺服器的臨時目錄內 -> 然後再以讀取普通檔案路徑的方式載入成File -> 再然後以流的方式輸出給客戶端彈窗另存為儲存 -> 最後關閉流並刪除伺服器路徑下的臨時檔案。
pom.xml
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.17</version>
</dependency>
前端js程式碼
//批次管理-下載批次匯入資料
function downloadBatchImportDataTaskActionColumn(taskId) {
var language = 'zh';
if(Cookies.get("language") != null && Cookies.get("language") != "")
{
language = Cookies.get("language") ;
}
var url = prefix + "/downloadBatchImportData?language=" + language;
var form = $("<form></form>").attr("action", url).attr("method", "post");
form.append($("<input></input>").attr("type", "hidden").attr("name", "taskId").attr("value", taskId));
form.appendTo('body').submit().remove();
}
後端Controller程式碼
/**
* 下載批次匯入資料
* 流程:
* 查詢資料庫判斷filedownLink欄位是否為空
* 為空:則代表舊資料,沒有gofd對應的下載檔案地址,因此把模板檔案返回給客戶端
* 不為空:則代表gofd已經上傳了對應的批次匯入檔案,且資料庫中儲存地址連結
* 透過filedownLink封裝成FiLE
* 判斷File在臨時目錄內是否存在
* 存在:則直接返回給客戶端,最後再把伺服器臨時目錄內檔案刪除
* 不存在:則透過http工具呼叫filedownLink封裝成File,將檔案寫入tempFilePath臨時目錄內,再把檔案File返回給客戶端,最後再把伺服器臨時目錄內檔案刪除
* @param req req
* @param response response
*/
@RequestMapping(value = "/downloadBatchImportData")
public void downloadBatchImportData(HttpServletRequest req, HttpServletResponse response) {
logger.info("-downloadBatchImportData-begin");
String taskId = req.getParameter("taskId");
OutputStream os = null;
InputStream io = null;
String tempFilePath = TEMP_FILE_PATH;
String fileName = "";
String language = req.getParameter("language");
Workbook wb = null;
try {
ImpExpTaskDetail impExpTaskDetail = isvcBatchTaskServiceMicro.selectTaskDetailByTaskId(taskId);
String filedownLink = impExpTaskDetail.getLink();
if (org.springframework.util.StringUtils.isEmpty(filedownLink)) {
fileName = MessageUtils.message("batch.template") + ".xlsx";
String templateFileName = BatchConstant.DOWNAD_TEMPLATE_NAME + "_" + language + BatchConstant.EXTENSION_XLSX;
SysUser sysUser = ShiroUtils.getSysUser();
logger.info("-downloadBatchImportData-taskId:{},language:{}", taskId, language);
if (isysUserService.get36kType(sysUser.getUserId()) == Poc36kEnum.POC6K.getType()) {
templateFileName = BatchConstant.DOWNAD_TEMPLATE_NAME + "6k" + "_" + language + BatchConstant.EXTENSION_XLSX;
}
File templateFile = org.springframework.util.ResourceUtils.getFile("classpath:" + templateFileName);
logger.info("-Template file exist!,templateFileName:{}", templateFileName);
io = new FileInputStream(templateFile);
wb = new XSSFWorkbook(io);
} else {
fileName = StringUtils.subscribeNameString(filedownLink);
File file = ResourceUtils.getFile(String.join(File.separator, tempFilePath, fileName));
if (!file.exists()) {
String begin = DateUtil.now();
DateTime beginTime = DateUtil.parse(begin);
long download = HttpUtil.downloadFile(filedownLink, FileUtil.file(tempFilePath, fileName), new StreamProgress() {
@Override
public void start() {
logger.info("開始下載,時間為:" + begin);
}
@Override
public void progress(long progressSize) {
logger.info("已下載:{}", FileUtil.readableFileSize(progressSize));
}
@Override
public void finish() {
String end = DateUtil.now();
DateTime endTime = DateUtil.parse(end);
long between = DateUtil.between(beginTime, endTime, DateUnit.MS);
logger.info("下載完成,用時:" + DateUtil.formatBetween(between, BetweenFormatter.Level.SECOND));
}
});
}
io = new FileInputStream(file);
wb = new XSSFWorkbook(io);
}
logger.info("-tempFilePath:{},fileName:{}", tempFilePath, fileName);
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
wb.write(response.getOutputStream());
} catch (IOException e) {
logger.error("-downloadBatchImportData error:{}", e.getMessage());
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
logger.error("-OutputStream error:{}", e.getMessage());
}
}
if (io != null) {
try {
io.close();
} catch (IOException e) {
logger.error("-InputStream error:{}", e.getMessage());
}
}
if (Optional.ofNullable(tempFilePath).isPresent()) {
// 強制刪除臨時檔案
boolean isDelete = com.hytalk.util.FileUtil.delFile(new File(tempFilePath));
logger.info("-downloadBatchImportData 強制刪除臨時檔案 , filePath: {} , isDelete : {} ", tempFilePath, isDelete);
}
}
}
FileUtil工具類
import java.io.File;
/**
* 檔案工具
* @Author 211145187
* @Date 2023/4/19 14:27
**/
public class FileUtil {
/**
* 刪除檔案
* @param file 檔案
* @return boolean
*/
public static boolean delFile(File file) {
if (!file.exists()) {
return false;
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
delFile(f);
}
}
return file.delete();
}
}
StringUtils工具類
/**
* 字串工具
* @author 211145187
* @Date: 2021/11/11 16:11
**/
public class StringUtils {
/**
* 擷取url地址中的名稱,比如路徑地址為“http://10.110.38.253:11014/group1/batchImportData/組 (26).xlsx”,最後擷取的名稱為“組 (26).xlsx”
* @param str 原字串
* @return 擷取後的字串
*/
public static String subscribeNameString(String str) {
if (str.lastIndexOf("/") > -1) {
str = str.substring(str.lastIndexOf("/") + 1);
}
return str;
}
}
說明:
只在意我的思路流程即可,至於工具類或者查資料庫資料程式碼啥的就不復制貼上了。