文件下载时间超时

···org.springframework.web.context.request.async.AsyncRequestTimeoutException: null
at org.springframework.web.context.request.async.TimeoutCallableProcessingInterceptor.handleTimeout(TimeoutCallableProcessingInterceptor.java:46)
at org.springframework.web.context.request.async.CallableInterceptorChain.triggerAfterTimeout(CallableInterceptorChain.java:82)
at org.springframework.web.context.request.async.WebAsyncManager$2.run(WebAsyncManager.java:293)
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:143)
at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44)
at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:131)
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:157)
at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:221)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
···

设置: spring.mvc.async.request-timeout= -1

转载于:https://www.cnblogs.com/liqingwang/p/10936491.html

<think>根据用户问题,需要在React中发起下载文件请求并设置超时时间。在JavaScript中,可以使用XMLHttpRequest或fetch API来实现网络请求,并设置超时。但下载文件通常涉及二进制数据,需要特殊处理。以下是一种常见方法: 1. 使用XMLHttpRequest,因为它支持设置timeout属性。 2. 设置请求的responseType为'blob',以便处理二进制文件。 3.超时时取消请求并处理错误。 另外,也可以使用fetch API结合AbortController来实现超时控制,但注意fetch本身没有timeout属性,需要手动实现超时。 下面分别给出两种实现方式: ### 方法1:使用XMLHttpRequest ```javascript function downloadFileWithTimeout(url, fileName, timeout = 10000) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.timeout = timeout; // 设置超时时间(毫秒) xhr.ontimeout = function () { reject(new Error('请求超时')); xhr.abort(); // 取消请求 }; xhr.onload = function () { if (xhr.status === 200) { const blob = xhr.response; const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = fileName; link.click(); window.URL.revokeObjectURL(link.href); resolve(); } else { reject(new Error(`请求失败,状态码: ${xhr.status}`)); } }; xhr.onerror = function () { reject(new Error('网络错误')); }; xhr.send(); }); } // 使用示例 downloadFileWithTimeout('https://example.com/file.pdf', 'downloaded.pdf', 15000) .catch(error => { console.error('下载失败:', error.message); // 这里可以添加错误处理,例如显示提示信息 }); ``` ### 方法2:使用fetch API和AbortController(推荐) fetch API更现代,但需要配合AbortController实现超时控制。 ```javascript function downloadFileWithTimeout(url, fileName, timeout = 10000) { const controller = new AbortController(); const signal = controller.signal; const timer = setTimeout(() => { controller.abort(); }, timeout); return fetch(url, { signal }) .then(response => { clearTimeout(timer); if (!response.ok) { throw new Error(`请求失败,状态码: ${response.status}`); } return response.blob(); }) .then(blob => { const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = fileName; link.click(); window.URL.revokeObjectURL(link.href); }) .catch(error => { clearTimeout(timer); if (error.name === 'AbortError') { throw new Error('请求超时'); } else { throw error; } }); } // 使用示例 downloadFileWithTimeout('https://example.com/file.pdf', 'downloaded.pdf', 15000) .catch(error => { console.error('下载失败:', error.message); // 错误处理 }); ``` ### 说明 - 两种方法都实现了超时控制,推荐使用fetch API,因为它更符合现代标准,并且可以更好地与React集成。 - 在React组件中使用时,可以将此函数放在事件处理函数(如按钮点击)中调用。 - 注意:下载文件可能会触发浏览器的安全策略,确保文件来源与当前页面同源或CORS配置允许。 ### 在React组件中的使用示例 ```jsx import React from 'react'; const DownloadButton = () => { const handleDownload = async () => { try { await downloadFileWithTimeout('https://example.com/file.pdf', 'downloaded.pdf', 15000); alert('下载成功!'); } catch (error) { alert(error.message); } }; return ( <button onClick={handleDownload}>下载文件</button> ); }; export default DownloadButton; ``` ### 注意事项 1. 跨域问题:如果文件在另一个域,需要服务器设置CORS响应头(如`Access-Control-Allow-Origin`)。 2. 错误处理:用户可能会遇到超时、网络错误或服务器错误,需要妥善处理。 3. 超时时间:根据文件大小和网络状况设置合理的超时时间。 以上方法在React中均可使用,且不依赖第三方库。 §§相关问题§§ 1. 如何处理下载文件时的进度显示? 2. 如何实现断点续传功能? 3. 在React中如何封装通用的文件下载钩子?</think>### 在 React 中设置下载文件请求的超时时间 在 React 中实现文件下载请求的超时控制,可以通过以下两种核心方法实现: #### 方法 1:使用 `fetch` + `AbortController`(推荐) ```javascript const downloadFile = async (url, filename, timeout = 10000) => { try { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeout); const response = await fetch(url, { signal: controller.signal, credentials: "include" // 携带 cookie }); clearTimeout(timer); if (!response.ok) throw new Error(`请求失败: ${response.status}`); const blob = await response.blob(); const objectUrl = URL.createObjectURL(blob); // 创建隐藏的下载链接 const link = document.createElement("a"); link.href = objectUrl; link.download = filename; document.body.appendChild(link); link.click(); // 清理资源 setTimeout(() => { URL.revokeObjectURL(objectUrl); document.body.removeChild(link); }, 100); } catch (error) { console.error("下载失败:", error.name === "AbortError" ? "请求超时" : error.message ); // 这里添加超时处理逻辑(例如显示错误提示) } }; // 在组件中使用 <button onClick={() => downloadFile("/api/file", "document.pdf", 15000)}> 下载文件(15秒超时) </button> ``` #### 方法 2:使用 `axios`(需安装 axios 库) ```javascript import axios from "axios"; const downloadWithAxios = async (url, filename, timeout = 10000) => { try { const response = await axios.get(url, { responseType: "blob", timeout, withCredentials: true }); const objectUrl = URL.createObjectURL(new Blob([response.data])); const link = document.createElement("a"); link.href = objectUrl; link.download = filename; link.click(); setTimeout(() => URL.revokeObjectURL(objectUrl), 100); } catch (error) { if (error.code === "ECONNABORTED") { console.error("请求超时"); } else { console.error("下载失败:", error.message); } } }; ``` ### 关键说明 1. **超时原理**: - `AbortController` 允许在指定时间后中止请求 - `axios` 内置 `timeout` 参数可直接设置超时 - 超时后触发 `AbortError` 或 `ECONNABORTED` 错误 2. **文件处理**: - 将响应转换为 Blob 对象 - 通过创建临时 URL 触发浏览器下载 - 使用 `URL.revokeObjectURL()` 释放内存[^4] 3. **跨域处理**: - 服务端需设置 `Access-Control-Allow-Origin` - 携带凭证需设置 `credentials: "include"`(fetch)或 `withCredentials: true`(axios) 4. **错误处理**: - 区分网络错误、服务器错误和超时错误 - 建议添加用户提示(如 Toast 通知) ### 完整组件示例 ```jsx import React, { useState } from "react"; const FileDownloader = () => { const [isLoading, setIsLoading] = useState(false); const handleDownload = async () => { setIsLoading(true); try { await downloadFile("/api/export", "report.xlsx", 15000); } catch (error) { alert(error.message); } finally { setIsLoading(false); } }; return ( <div> <button onClick={handleDownload} disabled={isLoading} > {isLoading ? "下载..." : "导出Excel报表"} </button> {isLoading && <div>正在下载(15秒超时控制)...</div>} </div> ); }; ``` ### 注意事项 1.文件下载建议结合进度提示,可通过 `axios` 的 `onDownloadProgress` 实现 2. 敏感文件应在服务端验证权限 3. 超时时间需根据文件大小和网络状况合理设置 4. 使用 `URL.revokeObjectURL()` 防止内存泄漏[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值