本文目录一览:
- 1、ajax如何 实现 文件上传
- 2、ajaxsubmit怎么提交文件
- 3、怎么用ajax实现上传文件的功能
- 4、如何用ajax上传文件
- 5、用ajax向后台aspx文件发送数据时,内容含有html代码不能发送成功吗?
- 6、多文件上传思路
ajax如何 实现 文件上传
程序说明
使用说明
实例化时,第一个必要参数是file控件对象:
new QuickUpload(file);
第二个可选参数用来设置系统的默认属性,包括
属性: 默认值//说明
parameter: {},//参数对象
action: "",//设置action
timeout: 0,//设置超时(秒为单位)
onReady: function(){},//上传准备时执行
onFinish: function(){},//上传完成时执行
onStop: function(){},//上传停止时执行
onTimeout: function(){}//上传超时时执行
还提供了以下方法:
upload:执行上传操作;
stop:停止上传操作;
dispose:销毁程序。
var QuickUpload = function(file, options) {
this.file = $$(file);
this._sending = false;//是否正在上传
this._timer = null;//定时器
this._iframe = null;//iframe对象
this._form = null;//form对象
this._inputs = {};//input对象
this._fFINISH = null;//完成执行函数
$$.extend(this, this._setOptions(options));
};
QuickUpload._counter = 1;
QuickUpload.prototype = {
//设置默认属性
_setOptions: function(options) {
this.options = {//默认值
action: "",//设置action
timeout: 0,//设置超时(秒为单位)
parameter: {},//参数对象
onReady: function(){},//上传准备时执行
onFinish: function(){},//上传完成时执行
onStop: function(){},//上传停止时执行
onTimeout: function(){}//上传超时时执行
};
return $$.extend(this.options, options || {});
},
//上传文件
upload: function() {
//停止上一次上传
this.stop();
//没有文件返回
if ( !this.file || !this.file.value ) return;
//可能在onReady中修改相关属性所以放前面
this.onReady();
//设置iframe,form和表单控件
this._setIframe();
this._setForm();
this._setInput();
//设置超时
if ( this.timeout 0 ) {
this._timer = setTimeout( $$F.bind(this._timeout, this), this.timeout * 1000 );
}
//开始上传
this._form.submit();
this._sending = true;
},
//设置iframe
_setIframe: function() {
if ( !this._iframe ) {
//创建iframe
var iframename = "QUICKUPLOAD_" + QuickUpload._counter++,
iframe = document.createElement( $$B.ie ? "iframe name=\"" + iframename + "\"" : "iframe");
iframe.name = iframename;
iframe.style.display = "none";
//记录完成程序方便移除
var finish = this._fFINISH = $$F.bind(this._finish, this);
//iframe加载完后执行完成程序
if ( $$B.ie ) {
iframe.attachEvent( "onload", finish );
} else {
iframe.onload = $$B.opera ? function(){ this.onload = finish; } : finish;
}
//插入body
var body = document.body; body.insertBefore( iframe, body.childNodes[0] );
this._iframe = iframe;
}
},
//设置form
_setForm: function() {
if ( !this._form ) {
var form = document.createElement('form'), file = this.file;
//设置属性
$$.extend(form, {
target: this._iframe.name, method: "post", encoding: "multipart/form-data"
});
//设置样式
$$D.setStyle(form, {
padding: 0, margin: 0, border: 0,
backgroundColor: "transparent", display: "inline"
});
//提交前去掉form
file.form $$E.addEvent(file.form, "submit", $$F.bind(this.dispose, this));
//插入form
file.parentNode.insertBefore(form, file).appendChild(file);
this._form = form;
}
//action可能会修改
this._form.action = this.action;
},
//设置input
_setInput: function() {
var form = this._form, oldInputs = this._inputs, newInputs = {}, name;
//设置input
for ( name in this.parameter ) {
var input = form[name];
if ( !input ) {
//如果没有对应input新建一个
input = document.createElement("input");
input.name = name; input.type = "hidden";
form.appendChild(input);
}
input.value = this.parameter[name];
//记录当前input
newInputs[name] = input;
//删除已有记录
delete oldInputs[name];
}
//移除无用input
for ( name in oldInputs ) { form.removeChild( oldInputs[name] ); }
//保存当前input
this._inputs = newInputs;
},
//停止上传
stop: function() {
if ( this._sending ) {
this._sending = false;
clearTimeout(this._timer);
//重置iframe
if ( $$B.opera ) {//opera通过设置src会有问题
this._removeIframe();
} else {
this._iframe.src = "";
}
this.onStop();
}
},
//销毁程序
dispose: function() {
this._sending = false;
clearTimeout(this._timer);
//清除iframe
if ( $$B.firefox ) {
setTimeout($$F.bind(this._removeIframe, this), 0);
} else {
this._removeIframe();
}
//清除form
this._removeForm();
//清除dom关联
this._inputs = this._fFINISH = this.file = null;
},
//清除iframe
_removeIframe: function() {
if ( this._iframe ) {
var iframe = this._iframe;
$$B.ie ? iframe.detachEvent( "onload", this._fFINISH ) : ( iframe.onload = null );
document.body.removeChild(iframe); this._iframe = null;
}
},
//清除form
_removeForm: function() {
if ( this._form ) {
var form = this._form, parent = form.parentNode;
if ( parent ) {
parent.insertBefore(this.file, form); parent.removeChild(form);
}
this._form = this._inputs = null;
}
},
//超时函数
_timeout: function() {
if ( this._sending ) { this._sending = false; this.stop(); this.onTimeout(); }
},
//完成函数
_finish: function() {
if ( this._sending ) { this._sending = false; this.onFinish(this._iframe); }
}
}
ajaxsubmit怎么提交文件
1、界面上直接使用submit按钮提交。这种方式可以实现效果但是没有success事件。即,可以上传文件,但是没有反馈信息。
2、使用jQuery的form方法提交表单,这种提交方式,可以对表单指定 onSubmit、success、error事件。这种方式会更加友好一些。
问题原因:通常使用Jquery就可以实现文件的上传。
怎么用ajax实现上传文件的功能
HTTP File Server
http-file-server 是用 python 实现的 HTTP 文件服务器,支持上传和下载文件。
运行
$ python file-server.py files 8001
其中第一个参数 files 是存放文件的路径,第二个参数 8001 是 HTTP 服务器端口。
接口
1. 读取文件
GET /pathtofile/filename
2. 读取文件夹下所有文件(已经忽略隐藏文件)
GET /path
返回文件列表为 JSON 数组,文件名末尾带有 / 的表示是文件夹。 filename 为文件名,mtime 为修改时间。
[{"filename":"f1.txt","mtime":1001},{"filename":"p3/","mtime":1002}]
3. 上传文件
采用 POST 方式上传文件,URL 参数中传参数 name 表示上传的文件名,POST 内容为文件内容。
POST /upload?name=filename
ajax 示例:
// file is a FileReader object
var data = file.readAsArrayBuffer();
var xhr = new XMLHttpRequest();
var url = "";
xhr.open("post", url, true);
xhr.setRequestHeader("Accept", "application/json, text/javascript, */*; q=0.01");
xhr.onreadystatechange = function() {
if (xhr.readyState==4 xhr.status==200)
{
console.log(xhr.responseText);
}
}
xhr.send(data);
文件名 filename 可以包含相对路径。比如:upload?name=md/xxx.md。则上传至 md 目录下。
如何用ajax上传文件
引入ajaxfileupload.js
jQuery.extend({
createUploadIframe: function(id, uri)
{
//create frame
var frameId = 'jUploadFrame' + id;
if(window.ActiveXObject) {
var io = document.createElement('iframe id="' + frameId + '" name="' + frameId + '" /');-ajaxaspx上传文件
if(typeof uri== 'boolean'){
io.src = 'javascript:false';
}
else if(typeof uri== 'string'){
io.src = uri;
}
}
else {
var io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
io.style.position = 'absolute';
io.style.top = '-1000px';
io.style.left = '-1000px';
document.body.appendChild(io);
return io
},
createUploadForm: function(id, fileElementId)
{
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = $('form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"/form');-ajaxaspx上传文件
var oldElement = $('#' + fileElementId);
var newElement = $(oldElement).clone();
$(oldElement).attr('id', fileId);
$(oldElement).before(newElement);
$(oldElement).appendTo(form);
//set attributes
$(form).css('position', 'absolute');
$(form).css('top', '-1200px');
$(form).css('left', '-1200px');
$(form).appendTo('body');
return form;
},
addOtherRequestsToForm: function(form,data)
{
// add extra parameter
var originalElement = $('input type="hidden" name="" value=""');
for (var key in data) {
name = key;
value = data[key];
var cloneElement = originalElement.clone();
cloneElement.attr({'name':name,'value':value});
$(cloneElement).appendTo(form);
}
return form;
},
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout-ajaxaspx上传文件
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var form = jQuery.createUploadForm(id, s.fileElementId);
if ( s.data ) form = jQuery.addOtherRequestsToForm(form,s.data);
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
// Watch for a new set of requests
if ( s.global ! jQuery.active++ )
{
jQuery.event.trigger( "ajaxStart" );
}
var requestDone = false;
// Create the request object
var xml = {}
if ( s.global )
jQuery.event.trigger("ajaxSend", [xml, s]);
// Wait for a response to come back
var uploadCallback = function(isTimeout)
{
var io = document.getElementById(frameId);
try
{
if(io.contentWindow)
{
xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;-ajaxaspx上传文件
xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;-ajaxaspx上传文件
}else if(io.contentDocument)
{
xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;-ajaxaspx上传文件
xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;-ajaxaspx上传文件
}
}catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if ( xml || isTimeout == "timeout")
{
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if ( status != "error" )
{
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData( xml, s.dataType );
// If a local callback was specified, fire it and pass it the data
if ( s.success )
s.success( data, status );
// Fire the global callback
if( s.global )
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
} else
jQuery.handleError(s, xml, status);
} catch(e)
{
status = "error";
jQuery.handleError(s, xml, status, e);
}
// The request was completed
if( s.global )
jQuery.event.trigger( "ajaxComplete", [xml, s] );
// Handle the global AJAX counter
if ( s.global ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
// Process result
if ( s.complete )
s.complete(xml, status);
jQuery(io).unbind()
setTimeout(function()
{ try
{
$(io).remove();
$(form).remove();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
}, 100)
xml = null
}
}
// Timeout checker
if ( s.timeout 0 )
{
setTimeout(function(){
// Check to see if the request is still happening
if( !requestDone ) uploadCallback( "timeout" );
}, s.timeout);
}
try
{
// var io = $('#' + frameId);
var form = $('#' + formId);
$(form).attr('action', s.url);
$(form).attr('method', 'POST');
$(form).attr('target', frameId);
if(form.encoding)
{
form.encoding = 'multipart/form-data';
}
else
{
form.enctype = 'multipart/form-data';
}
$(form).submit();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if(window.attachEvent){
document.getElementById(frameId).attachEvent('onload', uploadCallback);
}
else{
document.getElementById(frameId).addEventListener('load', uploadCallback, false);
}
return {abort: function () {}};
},
uploadHttpData: function( r, type ) {
var data = !type;
data = type == "xml" || data ? r.responseXML : r.responseText;
// If the type is "script", eval it in global context
if ( type == "script" )
jQuery.globalEval( data );
// Get the JavaScript object, if JSON is used.
if ( type == "json" )
{
// If you add mimetype in your response,
// you have to delete the 'pre/pre' tag.
// The pre tag in Chrome has attribute, so have to use regex to remove
var data = r.responseText;
var rx = new RegExp("pre.*?(.*?)/pre","i");
var am = rx.exec(data);
//this is the desired data extracted
var data = (am) ? am[1] : ""; //the only submatch or empty
eval( "data = " + data );
}
// evaluate scripts within html
if ( type == "html" )
jQuery("div").html(data).evalScripts();
//alert($('param', data).each(function(){alert($(this).attr('value'));}));
return data;
}
})
2.引入上传文件所需的jar
3.配置servlet.xml(不是web.xml)
4.jsp上传框
5.ajax传文件到后台
6.后台接收文件
7.获取之后怎么处理自己看着办咯,我只能帮到这里了
用ajax向后台aspx文件发送数据时,内容含有html代码不能发送成功吗?
在 Web
应用程序中,要阻止依赖于恶意输入字符串的黑客攻击,约束和验证用户输入是必不可少的。跨站点脚本攻击就是此类攻击的一个示例。其他类型的恶意数据或不需
要的数据可以通过各种形式的输入在请求中传入。通过在应用程序中的较低级别限制允许通过的数据类型,就可以阻止不希望的事件,即使当使用代码的程序员没有
恰当地使用合适的验证技术时也是如此。
当请求验证检测到潜在的恶意客户端输入时,会引发此异常来中止请求处理。请求中止能够指示危害您的应用程序安全的企图,例如跨站点脚本攻击。强烈建议让您的应用程序显式地检查与请求中止有关的所有输入。不过,您也可以通过将 @ Page 指令中的 validateRequest 属性设置为 false 来禁用请求验证,如下面的示例所示: -ajaxaspx上传文件
%@ Page validateRequest="false" %
含有html标记内容都是不安全的
加入validateRequest="false",页面就可以接收到了
多文件上传思路
给个例子吧:传几个地图文件到服务器
1)aspx文件:
%@ Page language="c#" Codebehind="AddMap.aspx.cs" AutoEventWireup="false" Inherits="ZiFengLast.SystemSet.AddMap" %-ajaxaspx上传文件
!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
HTML
HEAD
titleMapAdmin/title
meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR"
meta content="C#" name="CODE_LANGUAGE"
meta content="JavaScript" name="vs_defaultClientScript"
meta content="" name="vs_targetSchema"
LINK href="../StyleSheet1.css" type="text/css" rel="stylesheet"
script language="javascript"
function AddFile()
{
var rows=document.getElementById("rows").value;
var cols=document.getElementById("cols").value;
var FileList=document.getElementById("MyFile");
if(document.getElementById("MyFile").innerHTML.toString().length200)
{
// alert(document.getElementById("MyFile").innerHTML.toString().length);
FileList.innerHTML="font class='TagTitle'b 第1个地图:/b/font input style='WIDTH: 200px; HEIGHT: 22px' type='file' size='14' name='File'";-ajaxaspx上传文件
}
for(i=1;icols*rows;i++)
{
j=i+1;
var str ='font class="TagTitle"b 第'+j+'个地图:/b/font input style="WIDTH: 200px; HEIGHT: 22px" type="file" size="14" name="File"';-ajaxaspx上传文件
FileList.insertAdjacentHTML("beforeEnd","br");
FileList.insertAdjacentHTML("beforeEnd",str);
}
}
/script
/HEAD
body MS_POSITIONING="GridLayout"
form id="Form1" method="post" encType="multipart/form-data" runat="server"
FONT face="宋体"
TABLE id="Table1" style="BORDER-RIGHT: #33cc66 2px groove; BORDER-TOP: #33cc66 2px groove; Z-INDEX: 101; LEFT: 136px; BORDER-LEFT: #33cc66 2px groove; BORDER-BOTTOM: #33cc66 2px groove; POSITION: absolute; TOP: 32px"-ajaxaspx上传文件
width="500" align="center"
TBODY
TR height="20"
TD width="11%" /TD
TD width="11%" /TD
TD width="11%" /TD
TD width="11%" /TD
TD width="11%" /TD
TD width="11%" /TD
TD width="34%" /TD
/TR
TR
TD colSpan="2" /TD
TD colSpan="4"FONT class="WelcomeText" face="幼圆" color="#ff00ff" size="4" 添加新地图/FONT/TD
/TR
tr
td class="TagTitle" align="right" colSpan="3"b请选择地图规格: /b/td
td class="TagTitle" colSpan="2"input id="rows" style="WIDTH: 32px; HEIGHT: 22px" type="text" size="1" value="1" runat="server"-ajaxaspx上传文件
NAME="rows"行input id="cols" style="WIDTH: 32px; HEIGHT: 22px" type="text" size="1" value="1" runat="server"-ajaxaspx上传文件
NAME="cols"列/td
td colSpan="2" input style="WIDTH: 72px; HEIGHT: 22px" onclick="AddFile()" type="button" value="确定"/td-ajaxaspx上传文件
/tr
TR
TD class="TagTitle" align="right" width="33%" colSpan="3"B请选择地图文件:/B
/TD
TD class="TagTitle" width="33%" colSpan="4"/TD
/TR
tr
td colSpan="7"
p id="MyFile"font class="TagTitle"b 第1个地图:/b/font
input style="WIDTH: 200px; HEIGHT: 22px" type="file" size="14" name="File"
/p
/td
TR
TD class="TagTitle" align="right" width="33%" colSpan="3"B请输入地图存储名称:/B
/TD
TD class="TagTitle" align="left" width="33%" colSpan="4"INPUT id="MapName" style="WIDTH: 128px; HEIGHT: 22px" type="text" size="16" name="Password"-ajaxaspx上传文件
runat="server"
asp:requiredfieldvalidator id="RequiredFieldValidator2" runat="server" CssClass="TagTitle" ErrorMessage="地图名不能为空"-ajaxaspx上传文件
Font-Names="微软雅黑" Font-Size="X-Small" ControlToValidate="MapName"/asp:requiredfieldvalidator/TD-ajaxaspx上传文件
/TR
TR
TD class="TagTitle" style="HEIGHT: 29px" align="right" width="33%" colSpan="3"Basp:label id="Msg0" runat="server"/asp:label /B-ajaxaspx上传文件
/TD
TD class="TagTitle" style="HEIGHT: 29px" width="33%" colSpan="4"span class="ErrorMessage" id="OutputSpan" runat="server"asp:label id="Msg" runat="server"/asp:label/span/TD-ajaxaspx上传文件
/TR
TR
TD width="11%" /TD
TD width="11%" /TD
TD width="22%" colSpan="4"
asp:button id="SubmitButton" runat="server" Font-Names="微软雅黑" Font-Size="X-Small" Text="提交"
Height="26px" Width="60px"/asp:button INPUT id="CancelButton" style="FONT-SIZE: x-small; WIDTH: 60px; FONT-FAMILY: 微软雅黑; HEIGHT: 26px"-ajaxaspx上传文件
type="reset" value="清除" name="CancelButton"/TD
TD width="34%"
/TD
/TR
/TBODY
/TABLE
TABLE id="Table2" style="Z-INDEX: 102; LEFT: 136px; WIDTH: 491px; POSITION: absolute; TOP: 8px; HEIGHT: 26px"-ajaxaspx上传文件
width="491" align="center"
TR
TD class="TagTitle"A href="DeleteMap.aspx"FONT class="WelcomeText" face="幼圆"删除已有地图/FONT/A/TD
/TR
/TABLE
/FONT
/form
/TR/TBODY/TABLE/FONT
/body
/HTML
2)后台cs文件:关键是使用Request.Files获取刚上传的文件:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Configuration;
namespace ZiFengLast.SystemSet
{
/// summary
/// MapAdmin 的摘要说明。
/// /summary
public class AddMap : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button SubmitButton;
protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator2;
protected System.Web.UI.HtmlControls.HtmlGenericControl OutputSpan;
protected System.Web.UI.WebControls.Label Msg;
protected System.Web.UI.WebControls.Label Msg0;
protected System.Data.SqlClient.SqlConnection MapConn;
protected System.Data.SqlClient.SqlCommand MapComm;
protected System.Web.UI.HtmlControls.HtmlInputText rows;
protected System.Web.UI.HtmlControls.HtmlInputText cols;
protected System.Web.UI.HtmlControls.HtmlInputText MapName;
private void Page_Load(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/// summary
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// /summary
private void InitializeComponent()
{
this.MapConn = new System.Data.SqlClient.SqlConnection();
this.MapComm = new System.Data.SqlClient.SqlCommand();
this.SubmitButton.Click += new System.EventHandler(this.SubmitButton_Click);
//
// MapConn
//
this.MapConn.ConnectionString =System.Configuration.ConfigurationSettings.AppSettings["sqlMap"];
//
// MapComm
//
this.MapComm.Connection = this.MapConn;
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void SubmitButton_Click(object sender, System.EventArgs e)
{
try
{
HttpFileCollection file=Request.Files;
System.Text.StringBuilder FileNameArray=new System.Text.StringBuilder();
string SaveName=this.MapName.Value.Trim();
string FileExtension0=System.IO.Path.GetExtension(System.IO.Path.GetFileName(file[0].FileName));-ajaxaspx上传文件
for(int i=0;ifile.Count;i++)
{
HttpPostedFile PostFile=file[i];
string FileName=System.IO.Path.GetFileName(PostFile.FileName);
FileName.Replace(";","_");
string FileExtension=System.IO.Path.GetExtension(FileName);
string ContentType=PostFile.ContentType.ToString();
string LastSaveName=SaveName+(i+1).ToString()+FileExtension;
PostFile.SaveAs(Request.MapPath("../Map/"+LastSaveName));
FileNameArray.Append(LastSaveName);
FileNameArray.Append(";");
}
this.MapComm.CommandText="Select [Map].* from [Map] where MapName='"+SaveName+"'";
this.MapConn.Open();
System.Data.SqlClient.SqlDataReader rd=this.MapComm.ExecuteReader();
if(rd.Read())
{
this.MapConn.Close();
this.MapConn.Dispose();
this.MapComm.Dispose();
rd.Close();
Msg0.Text="font class=ErrorMessage上传文件失败!/font";
Msg.Text="font class=ErrorMessage已有该地图名称,请指定另外的名称/font";
}
else
{
rd.Close();
this.MapComm.CommandText="insert into [Map](MapName,MapRows,MapCols,MapFileNames) Values('"+SaveName+"',"+int.Parse(rows.Value)+","+int.Parse(cols.Value)+",'"+FileNameArray+"')";-ajaxaspx上传文件
//Response.Write(MapComm.CommandText);
this.MapComm.ExecuteNonQuery();
this.MapConn.Close();
this.MapConn.Dispose();
this.MapComm.Dispose();
}
Msg0.Text="font class=ErrorMessage上传文件成功!/font";
Msg.Text="font class=ErrorMessage共计上传文件"+file.Count.ToString()+"个"+"br"+FileNameArray+"/font";
}
catch(Exception ee)
{
Msg0.Text="font class=ErrorMessage上传文件失败!/font";
Msg.Text="font class=ErrorMessage"+ee.ToString()+"/font";
}
}
}
}