文件上传input type=“file“之accept接受的类型汇总

本文介绍了HTML中的<input>元素及其type属性,重点讲解了accept属性在文件上传中的作用,强调服务器端验证的重要性,列举了各种文件类型支持的MIME类型。
该文章已生成可运行项目,

 <input>标签

规定了用户可以在其中输入数据的输入字段。 <input> 元素在 <form> 元素中使用,用来声明允许用户输入数据的 input 控件。 输入字段可通过多种方式改变,取决于 type 属性。

<input> type 属性

type 属性规定要显示的 <input> 元素的类型。

<input> accept 属性

accept 属性规定了可通过文件上传提交的服务器接受的文件类型。

注意:accept 属性仅适用于 <input type="file">

提示:请不要将该属性作为您的验证工具。应该在服务器上对文件上传进行验证。

<input type="file" @change="getVod($event)" accept="audio/mp4, video/mp4">

类型:

.3gppaudio/3gpp, video/3gpp
.ac3audio/ac3
.asfallpication/vnd.ms-asf
.auaudio/basic
.csstext/css
.csvtext/csv
.docapplication/msword
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
.dotapplication/msword
.dotxapplication/vnd.openxmlformats-officedocument.wordprocessingml.template
.docmapplication/vnd.ms-word.document.macroEnabled.12
.dotmapplication/vnd.ms-word.template.macroEnabled.12
.dtdapplication/xml-dtd
.dwgimage/vnd.dwg
.dxfimage/vnd.dxf
.gifimage/gif
.htmtext/html
.htmltext/html
.jp2image/jp2
.jpeimage/jpeg
.jpegimage/jpeg
.jpgimage/jpeg
.jstext/javascript, application/javascript
.jsonapplication/json
.mp2audio/mpeg, video/mpeg
.mp3audio/mpeg
.mp4audio/mp4, video/mp4
.mpegvideo/mpeg
.mpgvideo/mpeg
.mppapplication/vnd.ms-project
.oggapplication/ogg, audio/ogg
.pdfapplication/pdf
.pngimage/png
.potapplication/vnd.ms-powerpoint
.potmapplication/vnd.ms-powerpoint.presentation.macroEnabled.12
.potxapplication/vnd.openxmlformats-officedocument.presentationml.template
.ppsapplication/vnd.ms-powerpoint
.ppsmapplication/vnd.ms-powerpoint.slideshow.macroEnabled.12
.ppsxapplication/vnd.openxmlformats-officedocument.presentationml.slideshow
.pptapplication/vnd.ms-powerpoint
.pptmapplication/vnd.ms-powerpoint.presentation.macroEnabled.12
.pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation
.ppaapplication/vnd.ms-powerpoint
.ppamapplication/vnd.ms-powerpoint.addin.macroEnabled.12
.rtfapplication/rtf, text/rtf
.svfimage/vnd.svf
.tifimage/tiff
.tiffimage/tiff
.txttext/plain
.wdbapplication/vnd.ms-works
.wpsapplication/vnd.ms-works
.xhtmlapplication/xhtml+xml
.xlcapplication/vnd.ms-excel
.xlmapplication/vnd.ms-excel
.xlaapplication/vnd.ms-excel
.xlamapplication/vnd.ms-excel.addin.macroEnabled.12
.xlsapplication/vnd.ms-excel
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xlsmapplication/vnd.ms-excel.sheet.macroEnabled.12
.xlsbapplication/vnd.ms-excel.sheet.binary.macroEnabled.12
.xltapplication/vnd.ms-excel
.xltxapplication/vnd.openxmlformats-officedocument.spreadsheetml.template
.xltmapplication/vnd.ms-excel.template.macroEnabled.12
.xlwapplication/vnd.ms-excel
.xmltext/xml, application/xml
.zipapplication/zipapplication/x-zip-compressed
本文章已经生成可运行项目
// src/components/UnifiedCsvMerger.tsx import React, { useState, useRef } from "react"; import Papa from "papaparse"; import { processDataList, generateTotalStats, filterPlayIdWithSuccessPriority } from "./utils"; import "./index.css"; // 引入抽离的样式 interface CsvRow { [key: string]: string; } const UnifiedCsvMerger: React.FC = () => { const fileInputRef = useRef<HTMLInputElement>(null); const [selectedFiles, setSelectedFiles] = useState<File[]>([]); const [mergedPreview, setMergedPreview] = useState<CsvRow[]>([]); // 缓存处理后的数据,用于切换展示 const [processedData, setProcessedData] = useState<CsvRow[]>([]); const [statsSummary, setStatsSummary] = useState<CsvRow[]>([]); const [statsSummaryUserImpact, setStatsSummaryUserImpact] = useState<CsvRow[]>([]); const [totalRows, setTotalRows] = useState<number | null>(null); const [isParsing, setIsParsing] = useState<boolean>(false); const [error, setError] = useState<string | null>(null); // 表单状态 const [formValues, setFormValues] = useState({ startTime: "", endTime: "", excludeErrorCodes: "-71114\n-71101\n-52208\n-1007\n-81607\n-80301\n-52405\n-1033\n-1029\n2\n-52407", targetEid: "Liveview.Video.StartPlay", }); // 单选选项类型 type OptionValue = "res" | "err_summary" | "err_summary_user_impact"; const options: { value: OptionValue; label: string }[] = [ { value: "res", label: "明细数据 (res)" }, { value: "err_summary", label: "错误统计汇总 (err_summary)" }, { value: "err_summary_user_impact", label: "错误统计汇总 (用户感知维度)" }, ]; const [selectedOption, setSelectedOption] = useState<OptionValue>("res"); // 添加文件 const handleAddFiles = (): void => { const files = fileInputRef.current?.files; if (!files || files.length === 0) return; const newFiles = Array.from(files).filter((file) => /\.(csv)$/i.test(file.name)); if (newFiles.length === 0) { alert("请选择有效的 CSV 文件"); return; } setSelectedFiles((prev) => [...prev, ...newFiles]); if (fileInputRef.current) fileInputRef.current.value = ""; }; // 删除文件 const handleRemoveFile = (index: number): void => { setSelectedFiles((prev) => prev.filter((_, i) => i !== index)); }; // 处理表单输入 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { const { name, value } = e.target; setFormValues((prev) => ({ ...prev, [name]: value, })); }; // 解析所有文件 const handleParseAll = (): void => { if (selectedFiles.length === 0) { setError("请先添加至少一个 CSV 文件"); return; } setIsParsing(true); setError(null); setMergedPreview([]); setTotalRows(0); const promises = selectedFiles.map( (file) => new Promise<CsvRow[]>((resolve) => { const rows: CsvRow[] = []; Papa.parse(file, { worker: false, header: true, skipEmptyLines: true, transform: (value) => value.trim(), step: (result) => { rows.push(result.data as CsvRow); }, complete: () => resolve(rows), error: () => resolve([]), }); }) ); Promise.all(promises) .then((allRows) => { const mergedData = allRows.flat(); // 构造配置项 const config = { start_time: formValues.startTime.trim() || undefined, end_time: formValues.endTime.trim() || undefined, exclude_error_codes: formValues.excludeErrorCodes .split(/[\n,;,\s]+/) .map((code) => code.trim()) .filter((code) => code !== ""), target_eid: formValues.targetEid.trim() || "Liveview.Video.StartPlay", }; // 核心处理 const res = processDataList(mergedData, config); const err_summary = generateTotalStats(res); const err_summary_user_impact = generateTotalStats(filterPlayIdWithSuccessPriority(res)); // 缓存结果供切换使用 setProcessedData(res); setStatsSummary(err_summary); setStatsSummaryUserImpact(err_summary_user_impact); // 默认显示明细数据前100条 setMergedPreview(res.slice(0, 100)); setTotalRows(mergedData.length); }) .catch((err: unknown) => { const message = err instanceof Error ? err.message : "未知错误"; setError(`解析过程中发生错误: ${message}`); }) .finally(() => { setIsParsing(false); }); }; // 处理单选按钮变化 const handleRadioChange = (e: React.ChangeEvent<HTMLInputElement>) => { const value = e.target.value as OptionValue; setSelectedOption(value); if (value === "res") { setMergedPreview(processedData.slice(0, 1000)); } else if (value === "err_summary") { setMergedPreview(statsSummary); } else if (value === "err_summary_user_impact") { setMergedPreview(statsSummaryUserImpact); } }; return ( <div className="unified-csv-merger"> <h2>📁 解析多个 CSV 文件(统一格式)</h2> {/* 添加文件 */} <div className="action-section"> <input ref={fileInputRef} type="file" accept=".csv" multiple onChange={handleAddFiles} disabled={isParsing} /> <button onClick={handleAddFiles} disabled={isParsing} className="add-btn"> 添加文件 </button> </div> {/* 已选文件列表 */} {selectedFiles.length > 0 && ( <div className="file-list"> <h3>📎 已选文件 ({selectedFiles.length}):</h3> <ul> {selectedFiles.map((file, index) => ( <li key={index}> <span title={file.name}> {file.name} <small>({(file.size / 1024).toFixed(1)} KB)</small> </span> <button onClick={() => handleRemoveFile(index)} disabled={isParsing} className="remove-btn"> 删除 </button> </li> ))} </ul> </div> )} {/* 过滤条件表单 */} <div className="filter-form"> <h3>⚙️ 数据处理配置</h3> <div className="form-group"> <label> 开始时间(可选) <input type="datetime-local" name="startTime" value={formValues.startTime} onChange={handleInputChange} className="form-control" /> </label> </div> <div className="form-group"> <label> 结束时间(可选) <input type="datetime-local" name="endTime" value={formValues.endTime} onChange={handleInputChange} className="form-control" /> </label> </div> <div className="form-group"> <label> 排除的错误码(每行一个,支持逗号/空格分隔) <textarea name="excludeErrorCodes" value={formValues.excludeErrorCodes} onChange={handleInputChange} rows={6} placeholder="例如: -71114 -1007 ..." className="form-control" /> </label> </div> <div className="form-group"> <label> 目标事件类型(target_eid) <input type="text" name="targetEid" value={formValues.targetEid} onChange={handleInputChange} placeholder="如:Liveview.Video.StartPlay" className="form-control" /> </label> </div> </div> {/* 解析按钮 */} <button onClick={handleParseAll} disabled={isParsing || selectedFiles.length === 0} className="parse-btn"> {isParsing ? "解析中..." : "🚀 解析并合并所有文件"} </button> {/* 错误提示 */} {error && <div className="error-message">{error}</div>} {/* 合并结果展示 */} {!isParsing && totalRows !== null && ( <div className="result-preview"> {/* 单选切换 */} <div className="radio-options"> <h3>请选择预览内容:</h3> {options.map((option) => ( <label key={option.value} style={{ display: "block", margin: "8px 0" }}> <input type="radio" value={option.value} checked={selectedOption === option.value} onChange={handleRadioChange} /> {option.label} </label> ))} <p> 当前显示: <strong>{options.find((o) => o.value === selectedOption)?.label}</strong> </p> </div> <h3>📊 预览结果</h3> <p> <strong>原始共 {totalRows.toLocaleString()} 行数据</strong>,当前展示为 {selectedOption === "res" ? "过滤后明细数据前100条" : "错误统计汇总"} </p> <div className="table-container"> <table> <thead> <tr> {Object.keys(mergedPreview[0] || {}).map((header) => ( <th key={header}>{header}</th> ))} </tr> </thead> <tbody> {mergedPreview.length > 0 ? ( mergedPreview.map((row, idx) => ( <tr key={idx}> {Object.values(row).map((cell, j) => ( <td key={j}>{cell}</td> ))} </tr> )) ) : ( <tr> <td colSpan={Object.keys(mergedPreview[0] || {}).length || 1} className="empty-row"> 暂无数据 </td> </tr> )} </tbody> </table> </div> </div> )} </div> ); }; export default UnifiedCsvMerger; 去掉所有的ts
10-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值