在项目的开发中。我们经常会遇到文件上传,在此,对文件上传进行一个梳理
文件上传的思路
在实现文件上传的时候,我们可以以文件来上传
也可以以流的形式上传
注意事项:
- android 系统分给每个app的内存较低,我们要想法进行缩小上传的文件体积
- 上传图片的时候,需要考虑图片的旋转角度(血泪史)
在上传前我们需要做的是压缩图片,生成临时图片
/**
* 只有图片,需要压缩
*/
private String[] getScaleFiles(String[] filePaths) {
ArrayList<String> list = new ArrayList<>();
// 创建一个临时的路径
String imgUploadFilePath = PathUtil.getDiskCacheDir(GlobalContext.getContext(), "temp").getAbsolutePath();
FileUtil.createNewFolder(imgUploadFilePath);
try {
for (String filePath : filePaths) {
if (FileUtil.isFileExists(filePath)) {
if (filePath.endsWith(".jpg") || filePath.endsWith(".png")) {
//判断为图片后,开始压缩大计。 主体原则为压缩后的图片,宽高不超过屏幕宽高
Bitmap scaleBitmap = BitmapUtil.getBitmapByPath(filePath, SCREEN_WIDTH, SCREEN_HEIGHT);
if (scaleBitmap != null) {
LogUtil.d("%s", "scaleBitmap img width " + scaleBitmap.getWidth() + " height " + scaleBitmap.getHeight());
//旋转为正常方向 并 对图片进行压缩处理
String path = getScaleImageFilePath(BitmapUtil.reviewPicRotate(scaleBitmap, filePath), imgUploadFilePath, filePath.hashCode() + ".jpg");
list.add(path);
//回收bitmap
if (scaleBitmap != null && !scaleBitmap.isRecycled()) {
LogUtil.d("recycle... %s", path);
scaleBitmap.recycle();
scaleBitmap = null;
}
} else {
//这种情况发生概率极低,需要手速
LogUtil.e("%s", "impossible file not exists " + filePath);
}
} else {
//这个理论上是视频。直接丢里面。丢啊丢啊丢手绢
list.add(filePath);
}
} else {
//如果用户在选择完图片,到了上传界面,还未点上传,但去sdcard下把图片删了,就会走这里
LogUtil.e("%s", "skip file not exists " + filePath);
}
}
} catch (OutOfMemoryError e) {
LogUtil.e(e.getMessage());
}
return CollectionUtil.listToArray(list);
}
/**
* 这里会把图片处理。取屏幕 宽or高 做最长边,等比缩小
*
* @param mBitmap
*/
private String getScaleImageFilePath(Bitmap mBitmap, String imgUploadFilePath, String fileName) {
if (mBitmap == null) {
LogUtil.w("getScaleImageFilePath bitmap is null");
ErrorUtil.report(GMNetRequest.class, "getScaleImageFilePath is null");
return "";
}
LogUtil.d("%s", "scale path " + imgUploadFilePath + File.separator + fileName);
File f = new File(imgUploadFilePath + File.separator + fileName);
try {
if (f.exists()) {
if (f.isDirectory()) {
//是目录那就是用户恶意创建的,防止下面崩溃,删掉
f.delete();
} else {
LogUtil.d("%s", "has exists " + fileName);
//如果图片已经处理过,就直接用了。不用再处理
return f.getAbsolutePath();
}
}
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//取img宽高
int imgWidth = mBitmap.getWidth();
int imgHeight = mBitmap.getHeight();
//求出 高 和 宽 的比
float scale = (float) imgHeight / imgWidth;
//取最长边
int max = imgWidth > imgHeight ? imgWidth : imgHeight;
if (max == imgWidth && imgWidth > SCREEN_WIDTH) {
//如果最长边是 宽,并且 宽 大于 屏幕宽度,就要处理
Float floatValue = Float.valueOf(SCREEN_WIDTH * scale);
int scaledheight = floatValue.intValue();
mBitmap = resizeImage(mBitmap, SCREEN_WIDTH, scaledheight);
} else if (max == imgHeight && imgHeight > SCREEN_HEIGHT) {
Float floatValue = Float.valueOf(SCREEN_HEIGHT / scale);
int scaledwidth = floatValue.intValue();
mBitmap = resizeImage(mBitmap, scaledwidth, SCREEN_HEIGHT);
}
if (mBitmap == null) {
return "";
}
LogUtil.i("%s", "after img width " + mBitmap.getWidth() + " mBitmap " + mBitmap.getHeight());
mBitmap.compress(Bitmap.CompressFormat.JPEG, 70, fOut);
try {
fOut.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
return f.getAbsolutePath();
}
直接以图片上传
使用httpClient框架来上传
以流的形式上传
在上面我们已经生成了一个临时的文件夹 里面包含了图片,我们需要的是将里面的所有图片生成流并上传
注意–上传的图片需要有 boundary 分隔符
private byte[] createByteData(String jsonData, String boundary, String[] filePaths) throws IOException {
StringBuilder js = new StringBuilder();
js.append(jsonData);
byte[] jsbyte = js.toString().getBytes("utf-8");
StringBuilder bound = new StringBuilder();
bound.append(boundary);
byte[] boundaryByte = bound.toString().getBytes("utf-8");
ByteArrayOutputStream dataBao = new ByteArrayOutputStream();
//上传文件规则是 json + 分隔符+ 文件 + 分隔符 + 文件。。。
dataBao.write(jsbyte);
for (String path : filePaths) {
LogUtil.d("upload file path %s ", path);
byte[] fileByte = readStream(path);
dataBao.write(boundaryByte);
dataBao.write(fileByte);
}
return dataBao.toByteArray();
}
private byte[] readStream(String filePath) throws IOException {
FileInputStream fs = new FileInputStream(filePath);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while (-1 != (len = fs.read(buffer))) {
outStream.write(buffer, 0, len);
}
outStream.close();
fs.close();
return outStream.toByteArray();
}
上面我们得到了文件的流–此时我们可以将流上传即可