webservice传输文件

来源:互联网 发布:编程来回打括号好烦 编辑:程序博客网 时间:2024/05/18 13:46

1. 通过webservice上传文件的原理

我们都知道如何通过WebService把一个字符串形式的参数传递到服务器端的一个函数并取得返回的结果,而通过WebService上传文件的原理和上传一个字符串在根本上是一样的。
唯一不同的是,我们需要多做一点额外的工作,即先读取文件到一个字节数组中,再通过Base64将其转化为字符串。详情请看下面的代码:
// 客户端读取文件然后用Base64将其转化为字符串的函数
private static String getFileByteString(File file) throws Exception{
InputStream in = new FileInputStream(file);

// 取得文件大小long length = file.length();// 根据大小创建字节数组byte[] bytes = new byte[(int) length];// 读取文件内容到字节数组int offset = 0;int numRead = 0;while (offset < bytes.length    && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {  offset += numRead;}// 读取完毕的校验  if (offset < bytes.length) {  throw new IOException("不能完全讀取文件:"+ file.getName());}in.close();String encodedFileString = Base64.encode(bytes);return encodedFileString;

}

服务器端如何将接收到的字符串还原成文件
有了上页函数的帮助,我相信你将它传递到WebSercvice端某函数是必能做到的事,剩下的问题是,如何将接收到的字符串还原成文件呢?
答案是再用Base64将字符串还原成字节数组再将它写入一个文件即可,这样写出来的文件能保证内容和你上传的原文件一致,下面是示例程序:

WebService服务器端将接收来的字符串还原的文件的过程
// uploadedFileString是传过来的包含你上传的文件内容的字符串
byte[] bytes = Base64.decode(uploadedFileString);

// 存储路径
String path=CommonUtil.getUploadPath();

// 存储的文件名
String localFileName=getLocalFileName(parser.getUserid(),parser.getFileName());

// 写入新文件
FileOutputStream out = new FileOutputStream(path+localFileName);
out.write(bytes);
out.flush();
out.close();

客户端如何访问已上传的文件

上传只是手段,我们上传的真正目的其实是下载,就我们刚才上传的文件而言,如何能让人访问到它呢?我们可以如下办理:
1.将上传文件书写在WebService所在Web应用下的某目录中,如upload”1.jpg,这样客户就可以通过这样的URL访问到这个文件http://209.205.177.42:8080/webApp/upload/1.jpg. 上面IP地址是WebSercice应用所在机器的公网地址,webApp是该应用名。
2.在客户端上传文件完毕后,将上述地址以函数返回值的形式告知客户,客户就可以通过网络来访问它了。

如何得到WebApp下的upload目录
书写一个在WebApp启动时就启动的Servlet,在其init函数就能得知Webapp所在目录,得到upload目录再往下走一层就行了。下面的InitServlet的示例代码:
public class InitialSystemServlet extends HttpServlet {

private static final long serialVersionUID = -7444606086930580188L;public void doPost(HttpServletRequest request, HttpServletResponse response)        throws ServletException, java.io.IOException {}public void doGet(HttpServletRequest request, HttpServletResponse response)        throws ServletException, java.io.IOException {    doPost(request, response);}public void init(ServletConfig config) throws ServletException {    // 设置上传路径    CommonUtil.setUploadPath(config.getServletContext().getRealPath("/"));}

}

其它问题
1.如何防止文件被覆盖:在生成文件时采用时间+用户ID+随机数的文件名,这样重名几率就大大降低,还不放心可以在写文件之间检验文件是否已存在了。
2.如何要把文件不放在服务器而是放到数据库怎么办:你可以把文件内容甚至字符串直接存储到数据库,需要下载时再取出来。

2. webservice二进制文件传输

最近boss要求做android客户端的图片上传和下载,就是调用服务器的webservice接口,实现从android上传图片到服务器,然后从服务器下载图片到android客户端。
需求下来了,开始动脑筋了呗。
通常,我们调用webservice,就是服务器和客户端(浏览器,android手机端等)之间的通信,其通信一般是传 xml或json格式的字符串。对,就只能是字符串。
我的思路是这样的,从android端用io流读取到要上传的图片,用Base64编码成字节流的字符串,通过调用webservice把该字符串作为参数传到服务器端,服务端解码该字符串,最后保存到相应的路径下。整个上传过程的关键就是 以 字节流的字符串 进行数据传递。下载过程,与上传过程相反,把服务器端和客户端的代码相应的调换。
不罗嗦那么多,上代码。流程是:把android的sdcard上某张图片 上传到 服务器下images 文件夹下。
注:这只是个demo,没有UI界面,文件路径和文件名都已经写死,运行时,相应改一下就行。
1 。读取android sdcard上的图片。
public void testUpload(){
try{
String srcUrl = “/sdcard/”; //路径
String fileName = “aa.jpg”; //文件名
FileInputStream fis = new FileInputStream(srcUrl + fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count = 0;
while((count = fis.read(buffer)) >= 0){
baos.write(buffer, 0, count);
}
String uploadBuffer = new String(Base64.encode(baos.toByteArray())); //进行Base64编码
String methodName = “uploadImage”;
connectWebService(methodName,fileName, uploadBuffer); //调用webservice
Log.i(“connectWebService”, “start”);
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
connectWebService()方法:
//使用 ksoap2 调用webservice
private boolean connectWebService(String methodName,String fileName, String imageBuffer) {
String namespace = “http://134.192.44.105:8080/SSH2/service/IService“; // 命名空间,即服务器端得接口,注:后缀没加 .wsdl,
//服务器端我是用x-fire实现webservice接口的
String url = “http://134.192.44.105:8080/SSH2/service/IService“; //对应的url
//以下就是 调用过程了,不明白的话 请看相关webservice文档
SoapObject soapObject = new SoapObject(namespace, methodName);
soapObject.addProperty(“filename”, fileName); //参数1 图片名
soapObject.addProperty(“image”, imageBuffer); //参数2 图片字符串
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER10);
envelope.dotNet = false;
envelope.setOutputSoapObject(soapObject);
HttpTransportSE httpTranstation = new HttpTransportSE(url);
try {
httpTranstation.call(namespace, envelope);
Object result = envelope.getResponse();
Log.i(“connectWebService”, result.toString());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
2。 服务器端的webservice代码 :
public String uploadImage(String filename, String image) {
FileOutputStream fos = null;
try{
String toDir = “C:\Program Files\Tomcat 6.0\webapps\SSH2\images”; //存储路径
byte[] buffer = new BASE64Decoder().decodeBuffer(image); //对android传过来的图片字符串进行解码
File destDir = new File(toDir);
if(!destDir.exists()) destDir.mkdir();
fos = new FileOutputStream(new File(destDir,filename)); //保存图片
fos.write(buffer);
fos.flush();
fos.close();
return “上传图片成功!” + “图片路径为:” + toDir;
}catch (Exception e){
e.printStackTrace();
}
return “上传图片失败!”;
}
对android 端进行 单元测试调用testUpload()方法,如果你看到绿条的话,说明调用成功!在服务器下,就可以看到你上传的图片了。。。。
当然,这个demo很简陋,没有漂亮UI什么的,但是这是 android端调用webservice进行上传图片的过程。从服务器下载到android端,道理亦然。欢迎大家交流学习。。。。

原创粉丝点击