本次任务:上传安卓客户端的res下的一张图片到服务器端的E盘下。
自己捣鼓这个作品时也真的费了劲,遇到三个小麻烦搞了两天才搞好。我越来越觉得能有个前辈在身边及时进行辅导能省下很多时间,可能这就是教师的儿女一般学习成绩都不错能上好大学的原因吧,教师比较闲相对来说又不断学习能给子女及时解答。
遇到的4个错误:
1:不知道怎么获取res下的某个图片的输入流?最后也是网络试了好多个别人的方法,这个通了
//图片数据难点
Resources r = HttpImageUpload.this.getBaseContext().getResources();
//取得对应图片的输入流,图片名字可以和最终写入的文件名不一致
//图片格式可以是png也可以是jpg
InputStream is = r.openRawResource(R.drawable.w);
2:一个错误:以为out.flush();包含了发送数据的功能,结果并不是,out.flush()只是清空掉暂时存储在内存缓冲区的所有数据,连接返回一个输入流才是发送数据并返回相应的信息
InputStream in=con.getInputStream();
3.一个错误无法解决:
服务端报错: Servlet.service() for servlet [android.HttpImageUpload] in context with path [/AndroidServer]threwexception[org.apache.tomcat.util.http.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream
最后发现是请求头Content-Type后面多加了冒号导致的。
4.在开发环境为AndroidStudio中和Eclipse中一模一样的代码,结果始终无法识别R.drawable.baby;
Error:Execution failed for task ':app:compileDebugJava'.
> Compilation failed; see the compiler error output for details.
网上说是开发工具的不一致导致的,在搞搞还是没用,最后用了
@SuppressWarnings("ALL")
错误就消失了,成功运行了,该批注是编译器对某些警告进行忽略的作用。
下面附上代码:
安卓客户端
package internethttp;
import android.content.res.Resources;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
import com.internethttp.R;
public class HttpImageUpload extends Activity {
public Button tv_btn;
public URL url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
tv_btn= (Button) findViewById(R.id.tv_btn);
try {
url=new URL("http://ly-and-tl.uicp.cn:42696/AndroidServer/HttpImageUpload");
} catch (MalformedURLException e) {
e.printStackTrace();
}
tv_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new httpImgThread(url).start();
}
});
}
class httpImgThread extends Thread{
URL URL;
String prefix="--";//结尾要在分隔符后加这个
//分隔符其实可以很随意指定数字,多少位都行,但注意的是正文比请求头的分隔符多出两个中杠
String boundary=UUID.randomUUID().toString();
String end="\r\n";//换行
httpImgThread(URL l){
URL=l;
System.out.println(boundary);
}
@Override
public void run() {
try {
// 第三种请求体的请求体被分成为多个部分,文件上传时会被使用,
// 这种格式最先应该是被用于邮件传输中,每个字段/文件都被boundary(Content-Type中指定)分成单独的段,
// 每段以-- 加 boundary开头,然后是该段的描述头,描述头之后空一行接内容
HttpURLConnection con=(HttpURLConnection)URL.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);//允许输出
con.setDoInput(true);//允许输入
//数据类型表单的形式,分隔符指定
con.setRequestProperty("Connection:", "keep-alive");
//请求消息头,以表单的形式发送数据到服务端,指定分隔符隔开不同的文件数据
//muiltipart/form-data可以以二进制方式上传文件
con.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary);
DataOutputStream out=new DataOutputStream(con.getOutputStream());
//分隔符换行,正文开始
out.writeBytes(prefix+boundary+end);
//指定键名,键值,name是控件的name,根据他后台找出对应图片,一个name标识一个文件
//含有filename会被当成一个文件
out.writeBytes("Content-Disposition:form-data;name=\"ooo\";"
+"fliename=\"upload.png\" " +end);
out.writeBytes(end);
//图片数据难点
Resources r = HttpImageUpload.this.getBaseContext().getResources();
//取得对应图片的输入流,图片名字可以和最终写入的文件名不一致
//图片格式可以是png也可以是jpg
InputStream is = r.openRawResource(R.drawable.w);
byte[] b=new byte[1024*4];
int len=0;
//读取图片数据
while((len=is.read(b))!=-1){
//is输入流读出来暂存到b中
out.write(b,0,len);
//将b中的数据写入out输出流中,从0开始的len个字节
}
//换行
out.writeBytes(end);
//分隔符换行后面多加--
out.writeBytes(prefix + boundary + prefix + end);
//并不发送,是清空缓冲区残存的的数据流
out.flush();
//下面才是发送请求并拿到返回的输入流
InputStream in=con.getInputStream();
if(out!=null)out.close();
if(is!=null)is.close();
if(in!=null) in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器端:
package android;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
//servlet3.0后简单的定义网址的方式
@WebServlet("/HttpImageUpload")
//指定文件上传的位置
@MultipartConfig(location="e:\\")//大小写都可以
public class HttpImageUpload extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//取出文件,根据前台请求发送的文件名name
//servlet3.0后才有的方法
Part part=request.getPart("ooo");
//写进文件名为upload.png的文件中
part.write("upload.png");
response.setCharacterEncoding("UTF-8");
}
}