日常随笔: 实现拖拽上传文件并展示
19. 拖拽上传图片并展示上传图片
1. 解决思路:
- 通过利用,监听drop方法,从dataTransfer中得到上传的源文件
- 利用FileReader类中的readAsDataURL将二进制文件转换成base64字符串
- 将该字符串放入img的src中即可
- 上传功能使用FormData进行处理,利用append方法添加内容
- 之后利用post上传到服务器,获取文件地址
1. 核心处理
详细内容见注释
- 浏览器读取文件并显示
const handleFileDrop = (e: React.DragEvent<HTMLDivElement>) => {//@ts-ignoree.preventDefault();// 获得拖动到页面上制定位置的文件内容const { files } = e.dataTransfer;const file = files[0];// 判断文件类型if (!file.type.startsWith("image")) {Notify.error("只能上传图片文件");return;}// 检验文件上传的大小if (!file) return;if (file.size > maxFileSize) {Notify.error("上传文件最大小不能超过10M");return;}// 读取文件到base64const reader = new FileReader();reader.readAsDataURL(file);// 当文件读取完毕时,保存为base64的字符串,后面img标签检测到变化后会自动渲染reader.onload = e => {const value = (e.target?.result as string) || "";setFileUrl(value);};// 报错setFile(file);
};
- 上传
const handleSubmit: IAvatarUploadProps["handleSubmit"] = async (file,setLoad
) => {setLoad(true);// 添加需要上传的文件const fileData = new FormData();fileData.append("file", file, file.name);// 添加完毕直接传就好了const { data } = await modifyAvatarApi(fileData);const { status, data: fileDetail, msg } = data;if (status) {const { filePath } = fileDetail;const { data } = await updateAvatarApi(userId, filePath);data.status ? Notify.success(msg) : Notify.error(msg);data.status &&(() => {dispatch({type: "login",payload: { ...state, avatarUrl: filePath }});setUserInfo({ ...userInfo, avatarUrl: filePath });window.localStorage.setItem("userToken", data.data.token);})();setLoad(false);closeDialog(dialogId);} else {Notify.error(msg);}
};// 上传API
export const modifyAvatarApi: TModifyAvatar = (data: FormData) =>Axios.post(`${URL}/modifyAvatar`, data, {headers: { "Content-Type": "multipart/form-data" }
});
2. 注意几个坑
dragOver和drop事件中一定要阻止默认事件,不然的话会直接把图片文件在浏览器中显示,或者下载!!
2. 实现效果

3. 完整代码
import React, { useState } from "react";
import styles from "./style.module.scss";
import { Notify, Icon, Button, BlockLoading } from "zent";export interface IAvatarUploadProps {maxFileSize: number;handleSubmit: (file: File,setLoad: React.Dispatch>) => void;
}export function AvatarUpload(props: IAvatarUploadProps) {const { maxFileSize, handleSubmit } = props;const [avatarFile, setFile] = useState();const [localUrl, setFileUrl] = useState();const [loading, setLoad] = useState(false);const handleDrageOver = (e: React.DragEvent) => {e.preventDefault();};const handleFileDrop = (e: React.DragEvent) => {//@ts-ignoree.preventDefault();const { files } = e.dataTransfer;const file = files[0];if (!file.type.startsWith("image")) {Notify.error("只能上传图片文件");return;}if (!file) return;if (file.size > maxFileSize) {Notify.error("上传文件最大小不能超过10M");return;}const reader = new FileReader();reader.readAsDataURL(file);reader.onload = e => {const value = (e.target?.result as string) || "";setFileUrl(value);};setFile(file);};return ({!(avatarFile && avatarFile.name) ? ({ 请选择你需上传的头像}) : (<>
{ fontSize: "20px", margin: "0 20px" }}/> 处理后图片 avatarFile && handleSubmit(avatarFile, setLoad)}type="primary"outline>提交修改>)} );
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
