Android端
1、首先需要用到的包,现在build.gradle(app)里边添加依赖
implementation 'com.github.xxl6097:okhttputils:2.4.1'
//或者implementation 'com.zhy:okhttputils:2.6.2'
//此处用的第一种
废话不多说,直接上代码
2、上传代码multiFileUpload方法
public void multiFileUpload(ArrayList<Image> image) throws UnsupportedEncodingException {
为json字符串并设置编码 .content(new Gson().toJson(new User("zhy", "123"))) //用Gson将User对象转化为Json字符串的形式作为content .build() .execute(new MyStringCallback()); }
mDialog = new SpotsDialog(SendFleaActivity.this,"上传中...");
final String url = AppConstant.uploadflea;
Map<String, String> headers = new HashMap<>();
headers.put("Content-Disposition", "form-data;filename=enctype");
PostFormBuilder build = OkHttpUtils.post();
for (int i=0;i<image.size();i++){
//判断文件合法
if(!new File(image.get(i).getPath()).exists()){
Toast.makeText(SendFleaActivity.this,"文件不存在,请修改路径",Toast.LENGTH_LONG).show();
return;
}
//压缩图片 获取到file格式
File file = new File(BitmapUtil.compressImage(image.get(i).getPath()));
//生成随即文件名,添加file,name是用户id
build.addFile(getuserid(getApplicationContext()),
getopenid(this)+
Universal.generateRandomFilename() +"01.png", file);
}
build.addHeader("head", URLEncoder.encode(getBean(), "UTF-8"))
.url(url)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e) {
mDialog.dismiss();
Toast.makeText(SendFleaActivity.this, "服务器连接失败",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
@Override
public void onResponse(Call call, String s) {
mDialog.dismiss();
try {
Toast.makeText(SendFleaActivity.this, URLDecoder.decode(s, "UTF-8"),Toast.LENGTH_LONG).show();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// if (s.equals("0")){
// Toast.makeText(SendFleaActivity.this, s+"发布成功",Toast.LENGTH_LONG).show();
// }else {
// Toast.makeText(SendFleaActivity.this,s+"发布失败",Toast.LENGTH_LONG).show();
//
// }
}
@Override
public void onBefore(Request request) {
super.onBefore(request);
mDialog.show();
}
});
}
3、代码注释较少,里边还用到了其他类的方法,比如给文件命名的随机文件名,就用到了随机函数,还是放一下generateRandomFilename()方法
public static String generateRandomFilename(){
String RandomFilename = "";
Random rand = new Random();//生成随机数
int random = rand.nextInt();
Calendar calCurrent = Calendar.getInstance();
int intDay = calCurrent.get(Calendar.DATE);
int intMonth = calCurrent.get(Calendar.MONTH) + 1;
int intYear = calCurrent.get(Calendar.YEAR);
String now = String.valueOf(intYear) + "_" + String.valueOf(intMonth) + "_" +
String.valueOf(intDay) + "_";
RandomFilename = "_"+now + String.valueOf(random > 0 ? random : ( -1) * random);
return RandomFilename;
}
4、其中的Image类
public class Image implements Parcelable {
private int id;
private String path;
private String thumbPath;
private boolean isSelect;
private String folderName;
private String name;
private long date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getThumbPath() {
return thumbPath;
}
public void setThumbPath(String thumbPath) {
this.thumbPath = thumbPath;
}
public boolean isSelect() {
return isSelect;
}
public void setSelect(boolean select) {
isSelect = select;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
@Override
public boolean equals(Object o) {
if (o instanceof Image) {
return this.path.equals(((Image) o).getPath());
}
return false;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.path);
dest.writeString(this.thumbPath);
dest.writeByte(this.isSelect ? (byte) 1 : (byte) 0);
dest.writeString(this.folderName);
dest.writeString(this.name);
dest.writeLong(this.date);
}
public Image() {
}
protected Image(Parcel in) {
this.id = in.readInt();
this.path = in.readString();
this.thumbPath = in.readString();
this.isSelect = in.readByte() != 0;
this.folderName = in.readString();
this.name = in.readString();
this.date = in.readLong();
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
@Override
public Image createFromParcel(Parcel source) {
return new Image(source);
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
}
5、压缩图片方法类BitmapUtil
public class BitmapUtil {
public static Bitmap calculateInSampleSize(String imagePath) {
// 设置参数
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 只获取图片的大小信息,而不是将整张图片载入在内存中,避免内存溢出
// 输出图像数据
//orginBitmap=: size: 14745600 width: 1440 heigth:2560
// Bitmap originBitmap = BitmapFactory.decodeFile(imagePath, options);
// Log.w("originBitmap=", "size: " + originBitmap.getByteCount() +
// " width: " + originBitmap.getWidth() + " height:" + originBitmap.getHeight());
int height = options.outHeight;
int width = options.outWidth;
int inSampleSize = 2; // 默认像素压缩比例,压缩为原图的1/2
int minLen = Math.min(height, width); // 原图的最小边长
if (minLen > 100) { // 如果原始图像的最小边长大于100dp(此处单位我认为是dp,而非px)
float ratio = (float) minLen / 100.0f; // 计算像素压缩比例
inSampleSize = (int) ratio;
}
options.inSampleSize = inSampleSize; // 设置为刚才计算的压缩比例
options.inJustDecodeBounds = false; // 计算好压缩比例后,这次可以去加载原图了
Bitmap bm = BitmapFactory.decodeFile(imagePath, options); // 解码文件
//size: 74256 width: 102 heigth:182
Log.w("bm=", "size: " + bm.getByteCount() + " width: " + bm.getWidth() + " heigth:" + bm.getHeight()); // 输出图像数据
return bm;
}
/**
* @param reqWidth 要求的宽
* @param reqHeight 要求的高
*/
public static Bitmap decodeSampledBitmapFromResource(String path, int reqWidth, int reqHeight) {
//Options 只保存图片尺寸大小,不保存图片到内存
BitmapFactory.Options options = new BitmapFactory.Options();
// 设置该属性为true,不加载图片到内存,只返回图片的宽高到options中。
// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
options.inJustDecodeBounds = true;
//先加载图片
BitmapFactory.decodeFile(path, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 重新设置该属性为false,加载图片返回
// 使用获取到的inSampleSize值再次解析图片
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) height / (float) reqHeight);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
return inSampleSize;
}
private static String PHOTO_FILE_NAME = "PMSManagerPhoto";
/**
* 获取图片的旋转角度
*
* @param filePath
* @return
*/
public static int getRotateAngle(String filePath) {
int rotate_angle = 0;
try {
ExifInterface exifInterface = new ExifInterface(filePath);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotate_angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate_angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate_angle = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return rotate_angle;
}
/**
* 旋转图片角度
*
* @param angle
* @param bitmap
* @return
*/
public static Bitmap setRotateAngle(int angle, Bitmap bitmap) {
if (bitmap != null) {
Matrix m = new Matrix();
m.postRotate(angle);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, true);
return bitmap;
}
return bitmap;
}
//转换为圆形状的bitmap
public static Bitmap createCircleImage(Bitmap source) {
int length = source.getWidth() < source.getHeight() ? source.getWidth() : source.getHeight();
Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(length, length, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);
canvas.drawCircle(length / 2, length / 2, length / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
/**
* 图片压缩-质量压缩
*
* @param filePath 源图片路径
* @return 压缩后的路径
*/
public static String compressImage(String filePath) {
//原文件
File oldFile = new File(filePath);
//压缩文件路径 照片路径/
String targetPath = oldFile.getPath();
int quality = 50;//压缩比例0-100
Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
int degree = getRotateAngle(filePath);//获取相片拍摄角度
if (degree != 0) {//旋转照片角度,防止头像横着显示
bm = setRotateAngle(degree,bm);
}
File outputFile = new File(targetPath);
try {
if (!outputFile.exists()) {
outputFile.getParentFile().mkdirs();
//outputFile.createNewFile();
} else {
outputFile.delete();
}
FileOutputStream out = new FileOutputStream(outputFile);
bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
return filePath;
}
return outputFile.getPath();
}
/**
* 根据路径获得图片信息并按比例压缩,返回bitmap
*/
public static Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
BitmapFactory.decodeFile(filePath, options);
// 计算缩放比
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// 完整解析图片返回bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
}
6、在文件上传的multiFileUpload里边,下边这句话是post一个头文件,这里我将我需要上传的文本信息放在这里,也可以放在param里边 但是我发现这样读取不到,很烦,没找到原因,暂且放到头文件,getBean()方法就是我的文本信息,此处自行修改,不需要的话直接删除
build.addHeader("head", URLEncoder.encode(getBean(), "UTF-8"))
然后好像就没有别的东西了,发现缺少什么代码请及时联系
那么此处就是所有的Android的东西了
服务端代码
照样废话不多说,直接上代码//额 咋还不让复制了,复制就崩,不知道是不是csdn的问题还是我的问题
/**
* Servlet implementation class UploadServlet
*/
@WebServlet(description = "flea商品发布",urlPatterns = {"/UploadServlet"})
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 上传文件存储目录
private static final String UPLOAD_DIRECTORY = "upload";
// 上传配置
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
private static String SUCCESS = null; // 50MB
private static String FAIL = null;
static {
try {
SUCCESS = URLEncoder.encode("发布成功", "UTF-8");
FAIL = URLEncoder.encode("发布失败", "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* 上传数据及保存文件
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
// 检测是否为多媒体上传
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// System.out.println("111"+getparam(request));
// 这一句的话 就是获取头文件的
String goods =
URLDecoder.decode(getHeadersInfo(request).getOrDefault("head","失败"), "UTF-8");
// System.out.println(goods);
saveImage(request,response, DBUtil.Insert_goods(goods));
// response.getWriter().println(back);
// 跳转到 message.jsp
// request.getServletContext().getRequestDispatcher("/message.jsp").forward(
// request, response);
}
public static void saveImage(HttpServletRequest request,HttpServletResponse response,int goodid) throws IOException {
// 配置上传参数
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
factory.setSizeThreshold(MEMORY_THRESHOLD);
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大文件上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
// Request.QueryString["name"];
// 构造临时路径来存储上传的文件
// 这个路径相对当前应用的目录
String uploadPath = request.getServletContext().getRealPath("./") + File.separator + UPLOAD_DIRECTORY;
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
Enumeration<String> enumeration = request.getParameterNames();
while(enumeration.hasMoreElements()){
String name = enumeration.nextElement();
String value = new String(request.getParameter(name).getBytes("iso8859-1"),"utf-8");
System.out.println(name+" : "+value);}
// 解析请求的内容提取文件数据
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
int i = 0;
// 迭代表单数据
for (FileItem item : formItems) {
// System.out.println(item.getFieldName());
// 处理不在表单中的字段
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
// System.out.println(item.getName()+"++++++++++++");
//将图片信息保存到数据库
if (goodid!=0) {
if (i==0){
DBUtil.Insert_one(DBUtil.TAB_flea_goods,goodid,"url",DBUtil.THIS_URL+item.getName());
i=2;
}
DBUtil.inser_image(DBUtil.TAB_flea_pic_url, goodid, item.getName());
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 在控制台输出文件的上传路径
System.out.println(filePath);
// 保存文件到硬盘
item.write(storeFile);
// request.setAttribute("message",
// "文件上传成功!");
}
// else {
// response.getWriter().println(FAIL);
request.setAttribute("message",
"错误信息: " + "发布失败");
// }
}
}response.getWriter().println(SUCCESS);
}
} catch (Exception ex) {
try {
response.getWriter().println(FAIL);
}catch (Exception e){
response.getWriter().close();
}
ex.printStackTrace();
// request.setAttribute("message",
// "错误信息: " + ex.getMessage());
}
}
*
* @param request
* @return
*/
public static Map<String, String> getHeadersInfo(HttpServletRequest request) {
Map<String, String> map = new HashMap<String, String>();
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
// System.out.println(key + ":" + value);
map.put(key, value);
}
return map;
}
}
其实这里只需要看saveImage方法就行,这就是保存图片的,剩下的都是我在数据库存储的过程,删掉即可,需要的可以参考,emm目前就这样,有啥子问题及时联系,虽然帮不了什么,,,,