项目中要用到一个从iPad上传截图到Server端的功能。在网上搜了好多资料,都只是简单的iOS端的代码,Server段的代码基本没有。
要有也是php的或者ASP.Net的,没有找到Java的。在这里把我参考网友资源,写的用Java Servlet接收iOS上传图片的方法贴出来,与大
家分享。
首先是在iOS中的上传动作:
第一种方式是把UIImage的data 转码成Base64,作为一个参数上传,关键代码如下:
NSString *imgPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Temp.png"];
// Write a UIImage to JPEG with minimum compression (best quality)
// The value 'image' must be a UIImage object
// The value '1.0' represents image compression quality as value from 0.0 to 1.0
//[UIImageJPEGRepresentation([_imgScreenShot image], 1.0) writeToFile:jpgPath atomically:YES];
[UIImagePNGRepresentation([_imgScreenShot image]) writeToFile:imgPath atomically:YES];
//NSData *imageData = [NSData dataWithContentsOfFile:imgPath];
//纯代码的Base64 编码
//NSString *base64= [Utilitys Base64Encode:imageData];
//NSData扩展的Base64编码
//NSString *base64= [imageData base64EncodedString];
//GTMBase64编码
//NSString *base64= [Utilitys encodeBase64Data:imageData];
//iOS7 自带的Base64编码
NSString *base64= [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[self sendScreenShot:[_txtAccount text] Password:[_txtPassword text] Report:[_txtReport text] To:[_txtTo text]
Content:base64];
以上把image的数据保存成文件,读取出来后编码成base64,调用sendScreenShot方法:
- (void) sendScreenShot:(NSString*)login Password:(NSString*)password
Report:(NSString*)report To:(NSString*)to Content:(NSString*)content{
NSLog(@"Call web service send screen shoot");
[[iBIService sharedService] setDelegate:self];
[Utilitys showWaitingWithMessage:self.view alpha:0.7 Message:@"正在发送截屏邮件,请稍候..."];
[[iBIService sharedService] sendScreenShot:login Password:password Report:report To:to Content:content];
}
再通过Service调用NSURLConnection上传图片:
-(void) sendScreenShot:(NSString *)account Password:(NSString *)password Report:(NSString *)report To:(NSString *)to Content:(NSString *)content{
NSLog(@"send Screen Shot with account:%@, password:%@,Report:%@,To:%@,Content Length:%d",account,password,report,to,[content length]);
[buf setData:nil];
type = SENDSCREENSHOT;
//added by Dumbbell Yang at 2014-08-07
//[Utilitys showAlert:nil title:@"Base 64 Length" message:[NSString stringWithFormat:@"%d",[content length]]];
content = [Utilitys encodeToPercentEscapeString:content];
NSString *requestString = [NSString stringWithFormat:@"login=%@&password=%@&report=%@&to=%@&content=%@",
account,password,report,to,content];
//NSLog(@"Request String:%@",requestString);
NSData *requestData = [NSData dataWithBytes:[requestString UTF8String]
length:[requestString length]];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:URI_SEND_SCREEN_SHOT,
[Utilitys getUserDefaults:KEY_IMS_SERVER DefaultValue:IMS_SERVER],
[Utilitys getUserDefaults:KEY_IMS_PORT DefaultValue:IMS_SERVER_PORT]]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:requestData];
//[request addValue:[[Utilitys getApp] httpHeader] forHTTPHeaderField:@"Cookie"];
/*异步请求*/
[self resetConnection];
mconnection = [[NSURLConnection alloc] initWithRequest:request
delegate:self startImmediately:YES];
timer = [NSTimer scheduledTimerWithTimeInterval:DATA_TIMEOUT target:self
selector:@selector(onTimeout) userInfo:nil repeats:NO];
}
J2EE Servlet端的接收代码如下:
//added by Dumbbell lYang at 2014-07-29
else if (strRequestURI.equals(SEND_SCREEN_SHOT)){
login = request.getParameter("login");
password = request.getParameter("password");
String report = request.getParameter("report");
String to = request.getParameter("to");
String content = URLDecoder.decode(request.getParameter("content"),"utf-8");
//added by Dumbbell Yang at 2014-08-11
content = content.replaceAll(" ", "+");
//added by Dumbbell Yang at 2014-08-06
System.out.println("Content Length(Base64):" + content.length());
writeToFile("Test64.jpg", content);
strOutput = ServiceManager.sendScreenShot(login, password,
report, to, content, mailServer,mailUserName,mailPassword);
}
这里要注意的就是对base64在iOS端编码后,要调用
content = [Utilitys encodeToPercentEscapeString:content]; 做一个URLEncode的动作。
然后在Servlet端接收时,先要decode:
String content = URLDecoder.decode(request.getParameter("content"),"utf-8");
然后因为还要记得把空格恢复成+:
//added by Dumbbell Yang at 2014-08-11
content = content.replaceAll(" ", "+");
然后就可以用base64 decode成byte文件,保存到Server了。
第二种方式是在iOS端构建form,把图片数据以二进制方式发送,主要参考了网友BorisSun的代码:
把UIImage的data保存成文件,然后传文件名:
[self sendScreenShotFile:[_txtAccount text] Password:[_txtPassword text] Report:[_txtReport text] To:[_txtTo text]
FilePath:imgPath];
调用sendScreenShotFile方法:
- (void) sendScreenShotFile:(NSString*)login Password:(NSString*)password
Report:(NSString*)report To:(NSString*)to FilePath:(NSString*)filePath{
NSLog(@"Call web service send screen shoot File");
[[iBIService sharedService] setDelegate:self];
[Utilitys showWaitingWithMessage:self.view alpha:0.7 Message:@"正在发送截屏邮件,请稍候..."];
[[iBIService sharedService] sendScreenShotFile:login Password:password Report:report To:to FilePath:filePath];
}
同样通过Service调用NSURLConnection,组织form Data上传图片:
//added by Dumbbell Yang at 2014-08-08
-(void) sendScreenShotFile:(NSString*)account Password:(NSString*)password Report:(NSString*)report To:(NSString*)to FilePath:(NSString*)filePath{
NSLog(@"send Screen Shot File with account:%@, password:%@,Report:%@,To:%@,File Path:%@",account,password,report,to,filePath);
[buf setData:nil];
type = SENDSCREENSHOTFILE;
NSString *TWITTERFON_FORM_BOUNDARY = @"0xKhTmLbOuNdArY";
//根据url初始化request
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:URI_SEND_SCREEN_SHOT_FILE,
[Utilitys getUserDefaults:KEY_IMS_SERVER DefaultValue:IMS_SERVER],
[Utilitys getUserDefaults:KEY_IMS_PORT DefaultValue:IMS_SERVER_PORT]]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
// cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
// timeoutInterval:10];
//分界线 --AaB03x
NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
//结束符 AaB03x--
NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
//得到图片的data
NSData* imgData = [NSData dataWithContentsOfFile:filePath];
//http body的字符串
NSMutableString *body=[[NSMutableString alloc]init];
//account or email
//添加分界线,换行
[body appendFormat:@"%@\r\n",MPboundary];
//添加字段名称,换2行
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"login"];
//添加字段的值
[body appendFormat:@"%@\r\n",account];
//password
[body appendFormat:@"%@\r\n",MPboundary];
//添加字段名称,换2行
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"password"];
//添加字段的值
[body appendFormat:@"%@\r\n",password];
//report
[body appendFormat:@"%@\r\n",MPboundary];
//添加字段名称,换2行
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"report"];
//添加字段的值
[body appendFormat:@"%@\r\n",report];
//to
[body appendFormat:@"%@\r\n",MPboundary];
//添加字段名称,换2行
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"to"];
//添加字段的值
[body appendFormat:@"%@\r\n",to];
//image data length
[body appendFormat:@"%@\r\n",MPboundary];
//添加字段名称,换2行
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"datalength"];
//添加字段的值
[body appendFormat:@"%d\r\n", [imgData length]];
if(filePath){
//image data
[body appendFormat:@"%@\r\n",MPboundary];
//声明pic字段,文件名为report
[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",@"file", report];
//声明上传文件的格式
[body appendFormat:@"Content-Type: image/png\r\n\r\n"];
}
//声明myRequestData,用来放入http body
NSMutableData *myRequestData=[NSMutableData data];
//将body字符串转化为UTF8格式的二进制
[myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
if(filePath){
//将image data加入
[myRequestData appendData:imgData];
}
//added by Dumbbell Yang at 2014-08-07
//[Utilitys showAlert:nil title:@"Image Data Length" message:[NSString stringWithFormat:@"%d",[imgData length]]];
//声明结束符:--AaB03x--
NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
//加入结束符--AaB03x--
[myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
//设置HTTPHeader中Content-Type的值
NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
//设置HTTPHeader
[request setValue:content forHTTPHeaderField:@"Content-Type"];
//设置Content-Length
[request setValue:[NSString stringWithFormat:@"%d", [myRequestData length]] forHTTPHeaderField:@"Content-Length"];
//设置http body
[request setHTTPBody:myRequestData];
//added by Dumbbell Yang at 2014-08-07
//[Utilitys showAlert:nil title:@"HTTPBody Length" message:[NSString stringWithFormat:@"%d",[myRequestData length]]];
//http method
[request setHTTPMethod:@"POST"];
/*异步请求*/
[self resetConnection];
mconnection = [[NSURLConnection alloc] initWithRequest:request
delegate:self startImmediately:YES];
timer = [NSTimer scheduledTimerWithTimeInterval:DATA_TIMEOUT target:self
selector:@selector(onTimeout) userInfo:nil repeats:NO];
}
J2EE Servlet端代码如下(这里用到了ServletFileUpload组件,本来想写一个简单纯Servlet的方法的,无奈功力不够):
//added by Dumbbell Yang at 2014-08-08
else if (strRequestURI.equals(SEND_SCREEN_SHOT_FILE)){
try {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(request);
String report = "";
String to = "";
String fileName = "";
while (iter.hasNext()) {
FileItemStream item = iter.next();
String fieldName = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
//普通表单数据
if (fieldName != null){
System.out.println("Field Name:" + fieldName);
if (fieldName.equalsIgnoreCase("login")){
login = new String(readInputStream(stream),"UTF-8");
System.out.println(fieldName + ":" + login);
}
else if (fieldName.equalsIgnoreCase("password")){
password = new String(readInputStream(stream),"UTF-8");
System.out.println(fieldName + ":" + password);
}
else if (fieldName.equalsIgnoreCase("report")){
report = new String(readInputStream(stream),"UTF-8");
System.out.println(fieldName + ":" + report);
}
else if (fieldName.equalsIgnoreCase("to")){
to = new String(readInputStream(stream),"UTF-8");
System.out.println(fieldName + ":" + to);
}
}
else{
System.out.println("field name is null");
}
}
else {
//文件数据
fileName = item.getName();
if(fileName == null || fileName.equals("")){
System.out.println("file name is null");
}
else{
System.out.println("File Name:" + fileName);
OutputStream out = new FileOutputStream(fileName);
int len=-1;
byte [] b = new byte[1024];
while((len = stream.read(b))!=-1){
out.write(b, 0, len);
}
stream.close();
out.close();
}
}
}
if (login.equals("")||password.equals("")||
report.equals("")||to.equals("")||fileName.equals("")){
strOutput = "{\"ErrorMessage\":\"Invalid post parameter!\"}";
}
else{
FileInputStream fis = new FileInputStream(fileName);
String content = Base64.encodeBytes(readInputStream(fis));
strOutput = ServiceManager.sendScreenShot(login, password,
report, to, content, mailServer,mailUserName,mailPassword);
}
}
else {
/*Enumeration en = request.getParameterNames();
while (en.hasMoreElements()) {
String paramName = (String) en.nextElement();
String paramValue = request.getParameter(paramName);
System.out.println(paramName + ":" + paramValue);
}*/
strOutput = "{\"ErrorMessage\":\"Invalid content type!\"}";
}
}
catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
strOutput = "{\"ErrorMessage\":\"file upload exception!\"}";
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
strOutput = "{\"ErrorMessage\":\"file read exception!\"}";
}
欢迎批评指正,欢迎相互探讨,共同提高。