ASIHTTPRequest系列 三 檔案上傳
五、檔案上傳
1、服務端
檔案上傳需要服務端的配合。我們可在本機搭建tomcat測試環境。關於tomcat在MacOSX下的安裝配置,參考作者另一博文《安裝Tomcat到Mac OSX》。
開啟Eclipse,新建web工程。在其中新建一個ServletUploadServlet:
import java.io.*;
import java.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;
publicclass UploadServletextends HttpServlet {
privatebooleanisMultipart;
private String filePath,title;
privateintmaxFileSize = 500 * 1024;
privateintmaxMemSize = 4 * 1024;
private File file ;
publicvoid init( ){
// 從web.xml的context_param中獲得上傳檔案目錄(/data).
filePath =
getServletContext().getInitParameter("file-upload");
}
publicvoiddoPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,java.io.IOException {
// 檢查表單是否帶有
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;
}
DiskFileItemFactoryfactory = new DiskFileItemFactory();
// 記憶體最大可快取尺寸
factory.setSizeThreshold(maxMemSize);
// 指定當資料超過記憶體最大可快取尺寸時,臨時檔案的目錄
factory.setRepository(new File(filePath+"temp"));
// 檔案上傳物件
ServletFileUpload upload = new ServletFileUpload(factory);
// 設定檔案上傳最大允許尺寸
upload.setSizeMax( maxFileSize );
try{
out.println("<%@pagecontentType='text/html; charset=GBK'%>");
out.println("<html>");
out.println("<head>");
out.println("<title>Servletupload</title>");
out.println("</head>");
out.println("<body>");
// 獲取multipart/form-data內容,其中每個field被分成不同part
List fileItems = upload.parseRequest(request);
// 列舉每個field
Iterator i = fileItems.iterator();
while ( i.hasNext () )
{
FileItem fi = (FileItem)i.next();
if ( !fi.isFormField() )// 如果field為File
{
// 獲取field的name或id
String fieldName = fi.getFieldName();
String fileName = fi.getName();
// 檔名中文處理
fileName=newString(fileName.getBytes(),"gbk");
out.println("file name:"+fileName+"<br>");
String contentType = fi.getContentType();
boolean isInMemory= fi.isInMemory();
long sizeInBytes= fi.getSize();
// 把上傳資料寫入本地磁碟
if(fileName.lastIndexOf("//") >= 0 ){
file = new File( filePath +
fileName.substring( fileName.lastIndexOf("//"))) ;
}else{
file = new File( 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=new String(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)
throws ServletException,java.io.IOException {
thrownew ServletException("GET method used with " +
getClass( ).getName( )+": POSTmethod required.");
}
}
再新建一個upload.jsp頁面作為測試:
<%@page contentType="text/html; charset=GBK" language="java" import="java.util.*"%>
<html>
<head>
<title>fbysss UploadBean 示例</title>
<!--meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"-->
<!--meta http-equiv="Content-Type"content="text/html; charset=gb2312"-->
</head>
<FORM name="form1" METHOD="POST"ACTION="UploadServlet" ENCTYPE="multipart/form-data">
<input name="title" type= "text"value="請選擇檔案">
<p>附件</p>
<p><input name="attach" type="FILE"id="attach" size="50"></p>
<input name="ok" type= "submit"value="提交">
</form>
</html>
選擇一個檔案進行上傳,然後到/data目錄下檢查該檔案是否上傳成功。
2、iPhone客戶端
新建類,選擇UIViewController subclass,並勾上“WithXIB 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"
@interface UploadViewController : UIViewController {
UIBarItem* button;
UIWebView* webView;
UIProgressView* progress;
ASIFormDataRequest *request;
NSURL *url;
}
@property(retain,nonatomic)IBOutlet UIBarItem* button;
@property(retain,nonatomic)IBOutlet UIProgressView* progress;
@property(retain,nonatomic)IBOutlet UIWebView* 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
NSStringEncoding enc=CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingMacChineseSimp);
[requestsetStringEncoding:enc];
[selfprintBytes:s encoding:enc];// 列印GBK編碼字元
[requestsetPostValue:s forKey:@"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:[error description] baseURL:url];
[buttonsetEnabled:YES];
}
-(void)printBytes:(NSString *)strencoding:(NSStringEncoding)enc{
NSLog(@"defaultCStringEncoding:%d",[NSStringdefaultCStringEncoding]);
//根據給定的字元編碼,打印出編碼後的字元陣列
constchar *bytes=[str cStringUsingEncoding:enc];
for (int i=0;i<strlen(bytes);i++){
NSLog(@"%d%X",(i+1),bytes[i]);
}
}
編譯、執行。點選go按鈕,程式執行效果如下: