jqueryajax文件上傳
Ⅰ ajax如何實現跨域上傳文件
ajax跨域實現方法之跨子域實現ajax:
要求:實現hello.com的頁面 非同步請求 blog.hello.com下的頁面
實現方法:藉助iframe,通過設置iframe的src屬性,嵌入blog.hello.com下的一個頁面,比如AjaxProxy.jsp,然後由該頁面去請求Ajax
AjaxProxy請求完畢後,通過parent對象把返回的數據回傳給hello.com的主頁面。因此,真正的非同步請求還是發生在blog.hello.com的域名下
注意:通過這種方法實現的跨子域ajax請求,需要在hello.com的請求頁面以及AjaxProxy.jsp頁面中設置同樣的域名,也就是document.domain = "coolkissbh.com";
注意:關於設置domain的問題,如果是跨全域,使用上面方法時候,firefox下會提示
Illegal document.domain value" code: "1009的錯誤,因此跨全域只能使用第二種方法處理返回的數據:AjaxProxy.jsp將ajax返回的數據保存到一個全局變數中,hello.com通過setInterval定時去判斷iframe的頁面是否載入完成,如果載入完成,則獲取AjaxProxy.jsp的全局變數值。然後再做其它處理。
Ⅱ jQuery+ajax文件上傳失敗,什麼原因
大部分 都是超出了 伺服器的上傳大小限制
還有就是 ajax 上傳類型是否正確設置 ,類型轉換檢查錯誤沒,示例代碼:
var data = new FormData();
data.append('file', $('input[type=file]')[0].files[0]);
$.ajax({
url: 'ajax.php',
data: data,
processData: false,
type: 'POST'
contentType: 'multipart/form-data',
mimeType: 'multipart/form-data',
success: function (data) {
alert(data);
}
});
Ⅲ jquery ajax多圖上傳顯示怎麼寫
首先我們在頁面上放置個上傳按鈕,使用POST提交到ajax.php。#ul_pics 用來顯示上傳完畢後的圖片。
<a class="btn" id="btn">上傳圖片</a> 最大500KB,支持jpg,gif,png格式。
<ul id="ul_pics" class="ul_pics clearfix"></ul>
接著,載入jQuery.js和plupload.full.min.js插件。
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="plupload/plupload.full.min.js"></script>
當點擊按鈕「上傳圖片」後,彈出選擇文件對話框,按 "ctrl" 選擇多圖片上傳。然後調用 uploader.start() 方法,開始上傳。上傳中間過程我們可以用 UploadProgress 方法來顯示文件進度,最後通過 FileUploaded 來顯示對應的圖片。通過瀏覽器控制台,會發現上傳一張圖片,會向後台ajax.php請求一次。
var uploader = new plupload.Uploader({ //創建實例的構造方法
runtimes: 'html5,flash,silverlight,html4',
//上傳插件初始化選用那種方式的優先順序順序
browse_button: 'btn',
// 上傳按鈕
url: "ajax.php",
//遠程上傳地址
flash_swf_url: 'plupload/Moxie.swf',
//flash文件地址
silverlight_xap_url: 'plupload/Moxie.xap',
//silverlight文件地址
filters: {
max_file_size: '500kb',
//最大上傳文件大小(格式100b, 10kb, 10mb, 1gb)
mime_types: [ //允許文件上傳類型
{
title: "files",
extensions: "jpg,png,gif"
}]
},
multi_selection: true,
//true:ctrl多文件上傳, false 單文件上傳
init: {
FilesAdded: function(up, files) { //文件上傳前
if ($("#ul_pics").children("li").length > 30) {
alert("您上傳的圖片太多了!");
uploader.destroy();
} else {
var li = '';
plupload.each(files,
function(file) { //遍歷文件
li += "<li id='" + file['id'] + "'><div class='progress'><span class='bar'></span><span class='percent'>0%</span></div></li>";
});
$("#ul_pics").append(li);
uploader.start();
}
},
UploadProgress: function(up, file) { //上傳中,顯示進度條
$("#" + file.id).find('.bar').css({
"width": file.percent + "%"
}).find(".percent").text(file.percent + "%");
},
FileUploaded: function(up, file, info) { //文件上傳成功的時候觸發
var data = JSON.parse(info.response);
$("#" + file.id).html("<div class='img'><img src='" + data.pic + "'/></div><p>" + data.name + "</p>");
},
Error: function(up, err) { //上傳出錯的時候觸發
alert(err.message);
}
}
});
uploader.init();
Ⅳ jsp中使用jquery的ajaxfileupload插件怎麼實現非同步上傳
JSP頁面中引入的script代碼
<script>
function
ajaxFileUpload()
{
$("#loading").ajaxStart(function(){
$(this).show();
})//開始上傳文件時顯示一個圖片
.ajaxComplete(function(){
$(this).hide();
});//文件上傳完成將圖片隱藏起來
$.ajaxFileUpload({
url:'AjaxImageUploadAction.action',//用於文件上傳的伺服器端請求地址
secureuri:false,//一般設置為false
fileElementId:'imgfile',//文件上傳空間的id屬性
<input
type="file"
id="imgfile"
name="file"
/>
dataType:
'json',//返回值類型
一般設置為json
success:
function
(data,
status)
//伺服器成功響應處理函數
{
alert(data.message);//從伺服器返回的json中取出message中的數據,其中message為在struts2中定義的成員變數
if(typeof(data.error)
!=
'undefined')
{
if(data.error
!=
'')
{
alert(data.error);
}else
{
alert(data.message);
}
}
},
error:
function
(data,
status,
e)//伺服器響應失敗處理函數
{
alert(e);
}
}
)
return
false;
}
</script>
struts.xml配置文件中的配置方法:
<struts>
<package
name="struts2"
extends="json-default">
<action
name="AjaxImageUploadAction"
class="com.test.action.ImageUploadAction">
<result
type="json"
name="success">
<param
name="contentType">text/html</param>
</result>
<result
type="json"
name="error">
<param
name="contentType">text/html</param>
</result>
</action>
</package>
</struts>
上傳處理的Action
ImageUploadAction.action
package
com.test.action;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
import
java.util.Arrays;
import
org.apache.struts2.ServletActionContext;
import
com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public
class
ImageUploadAction
extends
ActionSupport
{
private
File
imgfile;
private
String
imgfileFileName;
private
String
imgfileFileContentType;
private
String
message
=
"你已成功上傳文件";
public
File
getImgfile()
{
return
imgfile;
}
public
void
setImgfile(File
imgfile)
{
this.imgfile
=
imgfile;
}
public
String
getImgfileFileName()
{
return
imgfileFileName;
}
public
void
setImgfileFileName(String
imgfileFileName)
{
this.imgfileFileName
=
imgfileFileName;
}
public
String
getImgfileFileContentType()
{
return
imgfileFileContentType;
}
public
void
setImgfileFileContentType(String
imgfileFileContentType)
{
this.imgfileFileContentType
=
imgfileFileContentType;
}
public
String
getMessage()
{
return
message;
}
public
void
setMessage(String
message)
{
this.message
=
message;
}
@SuppressWarnings("deprecation")
public
String
execute()
throws
Exception
{
String
path
=
ServletActionContext.getRequest().getRealPath("/upload/mri_img_upload");
String[]
imgTypes
=
new
String[]
{
"gif",
"jpg",
"jpeg",
"png","bmp"
};
try
{
File
f
=
this.getImgfile();
String
fileExt
=
this.getImgfileFileName().substring(this.getImgfileFileName().lastIndexOf(".")
+
1).toLowerCase();
/*
if(this.getImgfileFileName().endsWith(".exe")){
message="上傳的文件格式不允許!!!";
return
ERROR;
}*/
/**
*
檢測上傳文件的擴展名是否合法
*
*/
if
(!Arrays.<String>
asList(imgTypes).contains(fileExt))
{
message="只能上傳
gif,jpg,jpeg,png,bmp等格式的文件!";
return
ERROR;
}
FileInputStream
inputStream
=
new
FileInputStream(f);
FileOutputStream
outputStream
=
new
FileOutputStream(path
+
"/"+
this.getImgfileFileName());
byte[]
buf
=
new
byte[1024];
int
length
=
0;
while
((length
=
inputStream.read(buf))
!=
-1)
{
outputStream.write(buf,
0,
length);
}
inputStream.close();
outputStream.flush();
}
catch
(Exception
e)
{
e.printStackTrace();
message
=
"文件上傳失敗了!!!!";
}
return
SUCCESS;
}
}
轉載,僅供參考。
Ⅳ jquery ajax 上傳文件怎麼搞
Query Ajax在web應用開發中很常用,它主要包括有ajax,get,post,load,getscript等等這幾種常用無刷新操作方法,接下來通過本文給大家介紹jquery ajax 上傳文件處理方式。
FormData對象
XMLHttpRequest Level 2添加了一個新的介面FormData.利用FormData對象,我們可以通過JavaScript用一些鍵值對來模擬一系列表單控制項,我們還可以使用XMLHttpRequest的send()方法來非同步的提交這個」表單」.比起普通的ajax,使用FormData的最大優點就是我們可以非同步上傳一個二進制文件.
所有主流瀏覽器的較新版本都已經支持這個對象了,比如Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。之前都是用原生js的XMLHttpRequest寫的請求
XMLHttpRequest方式
xhr.open("POST", uri, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Handle response.
alert(xhr.responseText); // handle response.
}
};
fd.append('myFile', file);
// Initiate a multipart/form-data upload
xhr.send(fd);
其實jquery的ajax也可以支持到的,關鍵是設置:processData 和 contentType 。
ajax方式
var formData = new FormData();
var name = $("input").val();
formData.append("file",$("#upload")[0].files[0]);
formData.append("name",name);
$.ajax({
url : Url,
type : 'POST',
data : formData,
// 告訴jQuery不要去處理發送的數據
processData : false,
// 告訴jQuery不要去設置Content-Type請求頭
contentType : false,
beforeSend:function(){
console.log("正在進行,請稍候");
},
success : function(responseStr) {
if(responseStr.status===0){
console.log("成功"+responseStr);
}else{
console.log("失敗");
}
},
error : function(responseStr) {
console.log("error");
}
});
Ⅵ jqueryajax不能上傳圖片
不能上傳的原因可能是jquery插件使用不正確。
解決方法:
1、在head之間加入jquery引用
<scripttype="text/javascript" src="jquery.js"></script>
<scriptsrc="project/js/jquery.form.js" type="text/javascript"></script>
<scriptsrc="project/js/fileload.js" type="text/javascript"></script>
2、定義fileload.js,代碼如下:
function createHtml(obj) {
var htmstr = [];
htmstr.push( "<form id='_fileForm' enctype='multipart/form-data'>");
htmstr.push( "<table cellspacing="0" cellpadding="3" style="margin:0 auto; margin-top:20px;">");
htmstr.push( "<tr>");
htmstr.push( "<td class="tdt tdl">請選擇文件:</td>");
htmstr.push( "<td class="tdt tdl"><input id="loadcontrol" type="file" name="filepath" id="filepath" /></td>");
htmstr.push( "<td class="tdt tdl tdr"><input type="button" onclick="fileloadon()" value="上傳"/></td>");
htmstr.push( "</tr>");
htmstr.push( "<tr> <td class="tdt tdl tdr" colspan='3'style='text-align:center;'><div id="msg"> </div></td> </tr>");
htmstr.push( "<tr> <td class="tdt tdl tdr" style=" vertical-align:middle;">圖片預覽:</td> <td class="tdt tdl tdr" colspan="2"><div style="text-align:center;"><img src="project/Images/NoPhoto.jpg"/></div></td> </tr>");
htmstr.push( "</table>")
htmstr.push( "</form>");
obj.html(htmstr.join(""));
}
function fileloadon() {
$("#msg").html("");
$("img").attr({ "src": "project/Images/processing.gif" });
$("#_fileForm").submit(function () {
$("#_fileForm").ajaxSubmit({
type: "post",
url: "project/help.aspx",
success: function (data1) {
var remsg = data1.split("|");
var name = remsg[1].split("/");
if (remsg[0] == "1") {
var type = name[4].substring(name[4].indexOf("."), name[4].length);
$("#msg").html("文件名:" + name[name.length - 1] + " --- " + remsg[2]);
switch (type) {
case ".jpg":
case ".jpeg":
case ".gif":
case ".bmp":
case ".png":
$("img").attr({ "src": remsg[1] });
break;
default:
$("img").attr({ "src": "project/Images/msg_ok.png" });
break;
}
} else {
$("#msg").html("文件上傳失敗:" + remsg[2]);
$("img").attr({ "src": "project/Images/msg_error.png" });
}
},
error: function (msg) {
alert("文件上傳失敗");
}
});
return false;
});
$("#_fileForm").submit();
}
3、服務端處理上傳。
protected void Page_Load(object sender, EventArgs e)
{
try
{
HttpPostedFile postFile = Request.Files[0];
//開始上傳
string _savedFileResult = UpLoadFile(postFile);
Response.Write(_savedFileResult);
}
catch(Exception ex)
{
Response.Write("0|error|上傳提交出錯");
}
}
public string UpLoadFile(HttpPostedFile str)
{
return UpLoadFile(str, "/UpLoadFile/");
}
public string UpLoadFile(HttpPostedFile httpFile, string toFilePath)
{
try
{
//獲取要保存的文件信息
string filerealname = httpFile.FileName;
//獲得文件擴展名
string fileNameExt = System.IO.Path.GetExtension(filerealname);
if (CheckFileExt(fileNameExt))
{
//檢查保存的路徑 是否有/結尾
if (toFilePath.EndsWith("/") == false) toFilePath = toFilePath + "/";
//按日期歸類保存
string datePath = DateTime.Now.ToString("yyyyMM") + "/" + DateTime.Now.ToString("dd") + "/";
if (true)
{
toFilePath += datePath;
}
//物理完整路徑
string toFileFullPath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath + toFilePath;
//檢查是否有該路徑 沒有就創建
if (!System.IO.Directory.Exists(toFileFullPath))
{
Directory.CreateDirectory(toFileFullPath);
}
//得到伺服器文件保存路徑
string toFile = Server.MapPath("~" + toFilePath);
string f_file = getName(filerealname);
//將文件保存至伺服器
httpFile.SaveAs(toFile + f_file);
return "1|" + toFilePath + f_file + "|" + "文件上傳成功";
}
else
{
return "0|errorfile|" + "文件不合法";
}
}
catch (Exception e)
{
return "0|errorfile|" + "文件上傳失敗,錯誤原因:" + e.Message;
}
}
/// <summary>
/// 獲取文件名
/// </summary>
/// <param name="fileNamePath"></param>
/// <returns></returns>
private string getName(string fileNamePath)
{
string[] name = fileNamePath.Split('\');
return name[name.Length - 1];
}
/// <summary>
/// 檢查是否為合法的上傳文件
/// </summary>
/// <param name="_fileExt"></param>
/// <returns></returns>
private bool CheckFileExt(string _fileExt)
{
string[] allowExt = new string[] { ".gif", ".jpg", ".jpeg", ".rar",".png" };
for (int i = 0; i < allowExt.Length; i++)
{
if (allowExt[i] == _fileExt) { return true; }
}
return false;
}
public static string GetFileName()
{
Random rd = new Random();
StringBuilder serial = new StringBuilder();
serial.Append(DateTime.Now.ToString("HHmmss"));
serial.Append(rd.Next(100, 999).ToString());
return serial.ToString();
}
4、運行defualt.aspx頁面以後顯示的效果是:
Ⅶ Jquery/ajax 如何以put方式上傳文件
using System.Data.OleDb;
using System.Data;
namespace _211
{
/// <summary>
/// DBQuery 的摘要說明。
/// </summary>
public sealed class DBQuery
{
static OleDbConnection conn=DBConnection.getConn();
static DataTable dt;
public static DataTable OpenQuery(string sql)
{
OleDbDataAdapter da=new OleDbDataAdapter(sql,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName)
{
OleDbDataAdapter da=new OleDbDataAdapter("select * from "+TableName,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count)
{
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" * from "+TableName,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,string IndexColumn,bool IsAsc)
{
OleDbDataAdapter da=new OleDbDataAdapter("select * from "+TableName+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc"),conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count,string IndexColumn,bool IsAsc)
{
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" * from "+TableName+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc"),conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,string[] column,bool IsCondition)
{
string tempsql="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)
{
if(IsCondition)
tempsql+=" and ";
else
tempsql+=",";
}
}
;
string sql="";
if(IsCondition)
sql="select * from "+TableName+" where "+tempsql;
else
sql="select "+tempsql+" from "+TableName;
OleDbDataAdapter da=new OleDbDataAdapter(sql,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,string[] column,string[] condition)
{
string tempsql="";
string tempsql2="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
for(int i=0;i<condition.Length;i++)
{
tempsql2+=condition[i];
if(i<condition.Length-1)tempsql2+=" and ";
}
OleDbDataAdapter da=new OleDbDataAdapter("select "+tempsql+" from "+TableName+" where "+tempsql2,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count,string[] column)
{
string tempsql="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" "+tempsql+" from "+TableName,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count,string[] column,string[] condition)
{
string tempsql="";
string tempsql2="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
for(int i=0;i<condition.Length;i++)
{
tempsql2+=condition[i];
if(i<condition.Length-1)tempsql2+=" and ";
}
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" "+tempsql+" from "+TableName+" where "+tempsql2,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count,string[] column,string IndexColumn,bool IsAsc)
{
string tempsql="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" "+tempsql+" from "+TableName+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc"),conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,int count,string[] column,string[] condition,string IndexColumn,bool IsAsc)
{
string tempsql="";
string tempsql2="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
for(int i=0;i<condition.Length;i++)
{
tempsql2+=condition[i];
if(i<condition.Length-1)tempsql2+=" and ";
}
OleDbDataAdapter da=new OleDbDataAdapter("select top "+count.ToString()+" "+tempsql+" from "+TableName+" where "+tempsql2+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc"),conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,string[] column,string IndexColumn,bool IsAsc,int PageSize,int Page)
{
string tempsql="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
string sql="";
if(Page==0)
sql="select top "+PageSize.ToString()+" "+tempsql+" from "+TableName+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc");
else
sql="select top "+PageSize.ToString()+" "+tempsql+" from "+TableName+" where "+IndexColumn+(IsAsc?">":"<")+"(select "+(IsAsc?"max":"min")+"("+IndexColumn+") from "+TableName+" where "+IndexColumn+" in (select top "+(Page*PageSize)+" "+IndexColumn+" from "+TableName+" order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc")+")) order by "+IndexColumn+" "+(IsAsc?"Asc":"Desc");
OleDbDataAdapter da=new OleDbDataAdapter(sql,conn);
dt=new DataTable();
try
{
da.Fill(dt);
}
catch(Exception ex)
{
throw ex;
}
finally
{
da.Dispose();
}
return dt;
}
public static DataTable OpenTable(string TableName,string[] column,string[] condition,string IndexColumn,bool IsAsc,int PageSize,int Page)
{
string tempsql="";
string tempsql2="";
for(int i=0;i<column.Length;i++)
{
tempsql+=column[i];
if(i<column.Length-1)tempsql+=",";
}
for(int i=0;i<condition.Length;i++)
{
tempsql2+=condition[i];
if(i<condition.Length-1)tempsql2+=" and ";
}
Ⅷ jquery不使用插件通過ajax方法上傳文件
傳統的表單也需要定義「multipart/form-data」這樣的方式,就是將文件轉成二進制流上傳到伺服器。而jquery的ajax本身貌似本身並沒有辦法讀取本地的文件形成二進制流上傳到伺服器。只能用插件來實現。
Ⅸ jquery 的$ajax;能實現AJAX上傳文件嗎
用formData對象
把files對象放到formData中去
也可以使用fileReader對象來獲取文件的base64編碼,然後把base64編碼直接post給後台。
Ⅹ Jquery AjaxForm插件上傳文件是如何跨域實現的
用jsonp。你網路一下jsonp就知道了。
JSON和JSONP雖然只有一個字母的差別,但其實他們根本不是一回事兒:JSON是一種數據交換格式,而JSONP是一種依靠開發人員的聰明才智創造出的一種非官方跨域數據交互協議。我們拿最近比較火的諜戰片來打個比方,JSON是地下黨們用來書寫和交換情報的「暗號」,而JSONP則是把用暗號書寫的情報傳遞給自己同志時使用的接頭方式。看到沒?一個是描述信息的格式,一個是信息傳遞雙方約定的方法。