ASIHTTPRequest系列(三):文件上传
五、文件上传
1、服务端
文件上传需要服务端的配合。我们可在本机搭建tomcat测试环境。关于tomcat在Mac OSX下的安装配置,参考作者另一博文《安装Tomcat到Mac OSX》。
打开Eclipse,新建web工程。在其中新建一个Servlet UploadServlet:
importjava.io.*;
importjava.util.*;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.commons.fileupload.FileItem;
importorg.apache.commons.fileupload.disk.DiskFileItemFactory;
importorg.apache.commons.fileupload.servlet.ServletFileUpload;
publicclassUploadServletextendsHttpServlet {
privatebooleanisMultipart;
privateStringfilePath,title;
privateintmaxFileSize= 500 * 1024;
privateintmaxMemSize= 4 * 1024;
privateFilefile;
publicvoidinit( ){
//从web.xml的context_param中获得上传文件目录(/data).
filePath=
getServletContext().getInitParameter("file-upload");
}
publicvoiddoPost(HttpServletRequest request,
HttpServletResponse response)
throwsServletException, java.io.IOException {
//检查表单是否带有ENCTYPE="multipart/form-data"
isMultipart= ServletFileUpload.isMultipartContent(request);
response.setContentType("text/html");
response.setCharacterEncoding("GBK");
java.io.PrintWriter out = response.getWriter( );
if( !isMultipart){
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet upload</title>");
out.println("</head>");
out.println("<body>");
out.println("<p>No file uploaded</p>");
out.println("</body>");
out.println("</html>");
return;
}
DiskFileItemFactory factory =newDiskFileItemFactory();
//内存最大可缓存尺寸
factory.setSizeThreshold(maxMemSize);
//指定当数据超过内存最大可缓存尺寸时,临时文件的目录
factory.setRepository(newFile(filePath+"temp"));
//文件上传对象
ServletFileUpload upload =newServletFileUpload(factory);
//设置文件上传最大允许尺寸
upload.setSizeMax(maxFileSize);
try{
out.println("<%@page contentType='text/html; charset=GBK'%>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet upload</title>");
out.println("</head>");
out.println("<body>");
//获取multipart/form-data内容,其中每个field被分成不同part
ListfileItems = upload.parseRequest(request);
//枚举每个field
Iteratori = fileItems.iterator();
while( i.hasNext () )
{
FileItem fi = (FileItem)i.next();
if( !fi.isFormField () )//如果field为File
{
//获取field的name或id
StringfieldName= fi.getFieldName();
String fileName = fi.getName();
//文件名中文处理
fileName=newString(fileName.getBytes(),"gbk");
out.println("file name:"+fileName+"<br>");
StringcontentType= fi.getContentType();
booleanisInMemory= fi.isInMemory();
longsizeInBytes= fi.getSize();
//把上传数据写入本地磁盘
if( fileName.lastIndexOf("//") >= 0 ){
file=newFile(filePath+
fileName.substring( fileName.lastIndexOf("//"))) ;
}else{
file=newFile(filePath+
fileName.substring(fileName.lastIndexOf("//")+1)) ;
}
fi.write(file) ;
out.println("Uploaded Filename: "+ fileName +"<br>");
}else{//如果field为Form Field
title=fi.getFieldName();
if(title.equals("title")){
title=newString(fi.get(),"gbk");
out.println("title:"+title+"<br>");
}
}
}
out.println("</body>");
out.println("</html>");
}catch(Exception ex) {
System.out.println(ex);
}
}
publicvoiddoGet(HttpServletRequest request,
HttpServletResponse response)
throwsServletException, java.io.IOException {
thrownewServletException("GET method used with "+
getClass( ).getName( )+": POST method required.");
}
}
再新建一个upload.jsp页面作为测试:
<%@pagecontentType="text/html; charset=GBK"language="java"import="java.util.*"%>
<html>
<head>
<title>fbysssUploadBean示例</title>
<!--metahttp-equiv="Content-Type" content="text/html;charset=iso-8859-1"-->
<!--metahttp-equiv="Content-Type" content="text/html;charset=gb2312"-->
</head>
<FORMname="form1"METHOD="POST"ACTION="UploadServlet"ENCTYPE="multipart/form-data">
<inputname="title"type="text"value="请选择文件">
<p>附件</p>
<p><inputname="attach"type="FILE"id="attach"size="50"></p>
<inputname="ok"type="submit"value="提交">
</form>
</html>
将工程部署到tomcat中,启动tomcat,访问http://localhost:8080/test/upload.jsp,显示界面如下:
选择一个文件进行上传,然后到/data目录下检查该文件是否上传成功。
2、iPhone客户端
新建类,选择UIViewController subclass,并勾上“With XIB for user interface”,命名为 UploadViewController。
用IB 打开 Xib 文件,在其中拖入1个 UIToolBar 、1个 UIBarButtonItem 和1个 UIWebView、1个UIProgressView:
在Xcode中声明必要的变量和 IBOutlet/IBAction:
#import<UIKit/UIKit.h>
#import"ASIFormDataRequest.h"
#import"ASIHTTPRequest.h"
@interfaceUploadViewController : UIViewController {
UIBarItem*button;
UIWebView*webView;
UIProgressView*progress;
ASIFormDataRequest*request;
NSURL*url;
}
@property(retain,nonatomic)IBOutletUIBarItem* button;
@property(retain,nonatomic)IBOutletUIProgressView* progress;
@property(retain,nonatomic)IBOutletUIWebView* webView;
-(IBAction)go;
-(void)printBytes:(NSString*)str encoding:(NSStringEncoding)enc;
@end
将所有出口正确地连接到UpdateController.xib 中,保存。
打开MainWindow.xib,拖一个UIViewController进去并将其Identifier改为UpdateController,再将它连接到Window对象的的rootViewController。
编写UIButton 的 Touch up inside 事件代码如下:
-(IBAction)go{
NSString* s=@"哈哈哈";
url=[NSURLURLWithString:@"http://localhost:8080/test/UploadServlet"];
request= [ASIFormDataRequestrequestWithURL:url];
//字符串使用GBK编码,因为servlet只识别GBK
NSStringEncodingenc=CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingMacChineseSimp);
[requestsetStringEncoding:enc];
[selfprintBytes:sencoding:enc];//打印GBK编码字符
[requestsetPostValue:sforKey:@"title"];
[requestsetFile:@"/Users/kmyhy/Documents/iphone/Iphone开发介绍.doc"forKey:@"attach"];
[requestsetDelegate:self];
[requestsetDidFinishSelector:@selector(responseComplete)];
[requestsetDidFailSelector:@selector(responseFailed)];
[buttonsetEnabled:NO];
[requeststartSynchronous];
}
-(void)responseComplete{
//请求响应结束,返回responseString
NSString*responseString = [requestresponseString];
[webViewloadHTMLString:responseStringbaseURL:url];
[buttonsetEnabled:YES];
}
-(void)respnoseFailed{
//请求响应失败,返回错误信息
NSError*error = [requesterror];
[webViewloadHTMLString:[errordescription]baseURL:url];
[buttonsetEnabled:YES];
}
-(void)printBytes:(NSString*)str encoding:(NSStringEncoding)enc{
NSLog(@"defaultCStringEncoding:%d",[NSStringdefaultCStringEncoding]);
//根据给定的字符编码,打印出编码后的字符数组
constchar*bytes= [strcStringUsingEncoding:enc];
for(inti=0;i<strlen(bytes);i++) {
NSLog(@"%d %X",(i+1),bytes[i]);
}
}
编译、运行。点击go按钮,程序运行效果如下: