做了很久的移动端,在工作中文件上传是经常用到的,最常见的莫过于上传图片了,比如移动端修改用户的头像,这就要用到文件上传的知识了。作为一个移动端菜鸟,实现文件文件上传之后常常会想后台是怎么接收文件的。
于是研究了一阵后台开发接口的知识。对于JavaWeb来说后台开发接口主要还是用到HttpServerlet。比如登录接口,后台应该会见一个Login的Serverlet类(猜的,毕竟没有真正开发市场用的Web项目),然后在Serverlet类中的doGet、doPost、doPut、doDelete中编写接口的接收客户端数据(HttpServletRequest)或者给客户端返回数据(HttpServletResponse)。举一个后台登录接口的小案例:
package com;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.omg.CORBA.UserException;
import com.google.gson.Gson;
public class Login extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
PrintWriter pw=resp.getWriter();
pw.print("request POST");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String userName=req.getParameter("userName");
String userPwd=req.getParameter("userPwd");
PrintWriter pw=resp.getWriter();
UserInfo userInfo=new UserInfo();
if(userName==null||userName.equals("")||userPwd==null||userName.equals("")){
//用户名密码为空
userInfo.setCode("-1");
userInfo.setStatus("fail");
userInfo.setDesc("userName or usePwd cant be null!");
}else{
if(userName.equals("streamlet")&&userPwd.equals("123")){
userInfo.setCode("0");
userInfo.setStatus("success");
userInfo.setDesc("My name is "+userName);
userInfo.setUserId("1");
userInfo.setUserName(userName);
//登录成功
}else{
//登录失败
userInfo.setCode("-1");
userInfo.setStatus("fail");
userInfo.setDesc("userName or userPwd Error!");
}
}
pw.print((new Gson().toJson(userInfo)));
}
}
使用:
String userName=req.getParameter("userName");
String userPwd=req.getParameter("userPwd");
接收客户端接口拼接的参数
使用:
PrintWriter pw=resp.getWriter();
pw.print("对应的JSON数据");
给客户端返回数据。这里我的代码是封装了一个用户的实体类,然后使用Gson把实体类封装成一个JSON数据返回客户端。这就是一般的接口,拼接接口为:
http://localhost:8080/LyWebTest/login?userName=streamlet&userPwd=123
效果如下图:
窃以为,主要有数据到后台就是长传数据了,比说接口中拼接的userName=streamlet,其实后台的Serverlet中的
String userName=req.getParameter("userName");就拿到了字符串数据streamlet,这也是属于数据上传吧。
但是,如果是文件呢,看了很多资料都说可以使用base64生成字符串然后上传。我是使用Xtuils进行的文件长传。Android移动端代码如下:
RequestParams params = new RequestParams();
String url="http://192.168.56.1:8080/LyWebTest/upload";
params.addBodyParameter("file", new File(paths.get(0)));
HttpUtils http = new HttpUtils();
http.send(HttpRequest.HttpMethod.POST, url, params, new RequestCallBack<String>() {
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
Log.d("streamlet","success");
}
@Override
public void onFailure(HttpException e, String s) {
Log.d("streamlet","failed");
}
});
后台接收使用commons-fileupload-1.2.1这个jar包进行文件接收,接收代码如下:
package com;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class Upload extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// 创建文件项目工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置文件上传路径
String upload = this.getServletContext().getRealPath("/upload/");
// 获取系统默认的临时文件保存路径,该路径为Tomcat根目录下的temp文件夹
String temp = System.getProperty("java.io.tmpdir");
// 设置缓冲区大小为 5M
factory.setSizeThreshold(1024 * 1024 * 5);
// 设置临时文件夹为temp
factory.setRepository(new File(temp));
// 用工厂实例化上传组件,ServletFileUpload 用来解析文件上传请求
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
// 解析结果放在List中
try {
List<FileItem> list = servletFileUpload.parseRequest(request);
for (FileItem item : list) {
String name = item.getFieldName();
InputStream is = item.getInputStream();
if (name.contains("content")) {
System.out.println(inputStream2String(is));
} else if (name.contains("file")) {
try {
inputStream2File(is, upload + "\\" + item.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
out.write("success");
} catch (FileUploadException e) {
e.printStackTrace();
out.write("failure");
}
out.flush();
out.close();
}
// 流转化成字符串
public static String inputStream2String(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = -1;
while ((i = is.read()) != -1) {
baos.write(i);
}
return baos.toString();
}
// 流转化成文件
public static void inputStream2File(InputStream is, String savePath)
throws Exception {
System.out.println("文件保存路径为:" + savePath);
File file = new File(savePath);
InputStream inputSteam = is;
BufferedInputStream fis = new BufferedInputStream(inputSteam);
FileOutputStream fos = new FileOutputStream(file);
int f;
while ((f = fis.read()) != -1) {
fos.write(f);
}
fos.flush();
fos.close();
fis.close();
inputSteam.close();
}
}
这样客户端上传图片后后台就能接收到文件,并且把文件保存在tomcat中的upload文件夹下(前提是要手动在那件一个文件夹,不然会包路径找不到异常)。效果如下:
实际开发中需要这个图片的文件名保存到到数据库中,用户需要这张图片的时候再重数据库中找到这个文件名,然后去到tomcat中的upload中找到该文件。移动端加载这张图片的接口是:host+upload/文件名,例如我这里的:
这就样了,感觉很6,哈哈...
文件下载
客户端想做一个下载电子书的功能,然后下载了一些.txt的电子书到电脑上面,然后把书名存在MySQL中,用手机来下载我电脑中的电子书。
后台代码:
//指定要下载的文件路径
private static final String fileDir = "d:/";
private void downloadFile(HttpServletResponse response,String aFileName) {
FileInputStream in = null;
ServletOutputStream out = null;
try {
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename="
+ aFileName);
in = new FileInputStream(fileDir + aFileName);
out = response.getOutputStream();
out.flush();
int aRead = 0;
while ((aRead = in.read()) != -1 & in != null) {
out.write(aRead);
}
out.flush();
} catch (Throwable e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
这样就能在指定的路径上下载文件。有的是把文件保存到tomcat中的WebApps中的,也可以这么写:
/**
* 下载中文文件,中文文件下载时,文件名要经过URL编码,否则会出现文件名乱码
*
* @param response
* @throws FileNotFoundException
* @throws IOException
*/
private void downloadChineseFileByOutputStream(HttpServletResponse response)
throws FileNotFoundException, IOException {
String realPath = this.getServletContext().getRealPath(
"/download/1.txt");// 获取要下载的文件的绝对路径
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);// 获取要下载的文件名
// 设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
response.setHeader("content-disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8"));
InputStream in = new FileInputStream(realPath);// 获取文件输入流
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);// 将缓冲区的数据输出到客户端浏览器
}
in.close();
}
客户端下载文件的方法:
http://blog.csdn.net/qq_27634797/article/details/49495611