Ajax Style File Uploading using Hidden iFrame

本文介绍了一种利用隐藏iframe实现AJAX风格文件上传的方法。通过JavaScript创建并操作iframe,可以实现在页面不刷新的情况下上传文件,并将服务器响应的内容展示到指定的HTML元素中。这种方法适用于希望在不离开当前页面的情况下完成文件上传需求的应用场景。

<html>
 
<script language="Javascript">
function fileUpload(form, action_url, div_id) {
    // Create the iframe...
    var iframe = document.createElement("iframe");
    iframe.setAttribute("id", "upload_iframe");
    iframe.setAttribute("name", "upload_iframe");
    iframe.setAttribute("width", "0");
    iframe.setAttribute("height", "0");
    iframe.setAttribute("border", "0");
    iframe.setAttribute("style", "width: 0; height: 0; border: none;");
 
    // Add to document...
    form.parentNode.appendChild(iframe);
    window.frames['upload_iframe'].name = "upload_iframe";
 
    iframeId = document.getElementById("upload_iframe");
 
    // Add event...
    var eventHandler = function () {
 
            if (iframeId.detachEvent) iframeId.detachEvent("onload", eventHandler);
            else iframeId.removeEventListener("load", eventHandler, false);
 
            // Message from server...
            if (iframeId.contentDocument) {
                content = iframeId.contentDocument.body.innerHTML;
            } else if (iframeId.contentWindow) {
                content = iframeId.contentWindow.document.body.innerHTML;
            } else if (iframeId.document) {
                content = iframeId.document.body.innerHTML;
            }
 
            document.getElementById(div_id).innerHTML = content;
 
            // Del the iframe...
            setTimeout('iframeId.parentNode.removeChild(iframeId)', 250);
        }
 
    if (iframeId.addEventListener) iframeId.addEventListener("load", eventHandler, true);
    if (iframeId.attachEvent) iframeId.attachEvent("onload", eventHandler);
 
    // Set properties of form...
    form.setAttribute("target", "upload_iframe");
    form.setAttribute("action", action_url);
    form.setAttribute("method", "post");
    form.setAttribute("enctype", "multipart/form-data");
    form.setAttribute("encoding", "multipart/form-data");
 
    // Submit the form...
    form.submit();
 
    document.getElementById(div_id).innerHTML = "Uploading...";
}
</script>
 
<!-- index.php could be any script server-side for receive uploads. -->
<form>
<input type="file" name="datafile" /></br>
<input type="button" value="upload"
        onClick="fileUpload(this.form,'index.php','upload'); return false;" >
<div id="upload"></div>
</form>
 
</html>
 原文链接: http://viralpatel.net/blogs/ajax-style-file-uploading-using-hidden-iframe/
你提到: > `info.file.status` 的值是 `"uploading"`,而不是 `"done"`,导致 `onChange` 中的逻辑没有执行。 这说明你**在文件上传过程中访问了 `onChange` 回调**,此时文件尚未上传完成,所以 `status` 是 `"uploading"`。 --- ## ✅ 正确理解 `Upload` 组件的 `status` 状态 Ant Design 的 `Upload` 组件中,`file.status` 有以下几种状态: | 状态 | 含义 | |------|------| | `uploading` | 文件正在上传 | | `done` | 文件上传成功 | | `error` | 文件上传失败 | | `removed` | 文件已被移除 | --- ## ✅ 为什么 `status` 一直是 `uploading`? 因为你可能在上传过程中就触发了逻辑判断,例如: ```ts onChange: (info) => { const file = info.file; if (file.status === 'done') { // 上传成功后的逻辑 } } ``` 但此时文件还在上传中,所以 `status` 是 `"uploading"`,不会进入 `if` 分支。 --- ## ✅ 如何正确监听上传完成? 你需要确保只在上传完成后才执行你的逻辑。 ### ✅ 推荐写法: ```ts onChange: (info) => { const file = info.file; const fileList = info.fileList; if (file.status === 'done') { // 上传成功 message.success(`${file.name} 上传成功`); const filePath = file.response?.filePath || '#'; setFileList([file]); form.setFieldsValue({ uploadedFilePath: filePath }); } else if (file.status === 'removed') { // 文件被删除 setFileList([]); form.setFieldsValue({ uploadedFilePath: null }); } else if (file.status === 'error') { // 上传失败 message.error(`${file.name} 上传失败`); } else if (file.status === 'uploading') { // 正在上传 console.log('文件正在上传:', file.name); } // 始终更新 fileList 以保持 UI 同步 setFileList(fileList); }, ``` --- ## ✅ 关键点:`fileList` 必须同步到组件 你必须将 `fileList` 更新后重新设置回去,否则 UI 不会更新。 ```ts setFileList(fileList); ``` 否则: - 删除文件时不会刷新 UI; - 多个文件上传顺序会混乱; - 文件状态不会更新。 --- ## ✅ 示例:上传成功后显示文件 ```tsx { fileList.map(file => ( <div key={file.uid}> <a href={file.url || file.response?.filePath} target="_blank" rel="noopener noreferrer"> {file.name} </a> </div> )); } ``` --- ## ✅ 完整的 `uploadProps` 示例 ```ts const uploadProps = { name: 'multipartFile', action: 'http://localhost:8040/ds/dsdemo/addfile', maxCount: 1, withCredentials: true, fileList: fileList, onChange: (info) => { const file = info.file; const fileList = info.fileList; if (file.status === 'done') { message.success(`${file.name} 上传成功`); const filePath = file.response?.filePath || '#'; form.setFieldsValue({ uploadedFilePath: filePath }); } else if (file.status === 'removed') { setFileList([]); form.setFieldsValue({ uploadedFilePath: null }); } else if (file.status === 'error') { message.error('上传失败'); } setFileList(fileList); }, onRemove: () => { setFileList([]); form.setFieldsValue({ uploadedFilePath: null }); return true; }, }; ``` 并在 `Modal` 中绑定: ```tsx <Upload {...uploadProps}> <Button>选择文件</Button> </Upload> ``` --- ## ✅ 补充:如何调试上传状态? ```ts console.log('当前文件:', file); console.log('当前状态:', file.status); console.log('响应数据:', file.response); console.log('文件列表:', fileList); ``` --- ## ✅ 总结 | 问题 | 原因 | 解决方案 | |------|------|----------| | `status` 是 `"uploading"` | 文件正在上传中 | 使用 `if (file.status === 'done')` 判断上传完成 | | 文件上传后不显示 | 没有更新 `fileList` | 使用 `setFileList(fileList)` 同步更新 | | `file.response` 是 `undefined` | 后端返回格式不对 | 确保后端返回 JSON 格式 | | 删除文件无效 | 没有处理 `onRemove` | 添加 `onRemove` 回调 | --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值