问题描述
在 Step 步骤条中使用 ImageUploader 组件上传图片后,切换到步骤二,再回到步骤一,发现步骤一中ImageUploader 组件预览图片失败,再切换回步骤二,发现步骤二中的ImageUploader 组件也是一样预览图片失败,如下图:
原因分析
ImageUploader 组件上传图片后,会生成一个 blob url 用来展示图片, blob url 是 URL.createObjectURL() 方法返回的一段带 hash 的url,会一直存储在内存中, 直到document触发了unload事件(例如:document close)或者执行revokeObjectURL来释放。当切换到下一个步骤时,前一个步骤的组件被卸载,ImageUploader 组件创建的 blob url 在内存中被释放,ImageUploader 找不到改 blob url 在内存中的存储地址,因此无法展示图片。
解决方案
在切换回前一个步骤时,使用 URL.createObjectURL() 方法重新创建 blob url
export function Uploader(props) {
const value = props.value;
// 处理 value,解决 blob url 失效的问题
// 在 Form 中使用 UploadImage 组件,从 props 中可以取到 value
// 在 非 From 中使用 UploadImage 组件,props 中没有 value
if (value) {
props.value =
value &&
Array.isArray(value) &&
value?.map(item => {
if (item?.response?.file) {
// createObjectURL返回一段带hash的url,并且一直存储在内存中,直到document触发了unload事件(例如:document close)或者执行revokeObjectURL来释放
// 内存中释放了该 url 后,upload 组件不再展示图片,需要重新创建
const objUrl = URL.createObjectURL(item.response.file);
item.response.url = objUrl;
item.response.fileURL = objUrl;
item.response.downloadURL = objUrl;
item.url = objUrl;
item.downloadURL = objUrl;
item.imgURL = objUrl;
}
return item;
});
}
return (
<ImageUploader
maxCount={2}
upload={file => {
var fileUrl = URL.createObjectURL(file);
console.log('uploading', file, fileUrl);
props.onProgress && props.onProgress();
const fileUploadConfig = ventureFileBrokerConfig();
return fbupload({
file,
multipart: { host: fileUploadConfig.host, bizCode: fileUploadConfig.bizCode, path: fileUploadConfig.path },
}).then(result => {
console.log('image upload result', result);
props.onSuccess() && props.onSuccess();
// 图片上传没有返回 filename,让图片上传组件报错
if (!result.filename) return { url: '' };
return {
file,
key: result.filename,
id: result.filename,
url: fileUrl,
downloadURL: fileUrl,
thumbnailUrl: fileUrl,
fileName: result.filename,
name: result.filename,
fileURL: fileUrl,
};
});
}}
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp, application/pdf"
value={props.value}
{...props}
/>
);
}