问题描述:
当用户上传的图片太大时,如6M。此时生成的缩略图显示有问题(部分图片为黑色,没有压缩完全)
问题分析:
1.(压缩的)原图有问题。
2. 压缩过程的代码有问题。
最初版本 设计流程 图片上传并压缩的思路:
app中上传图片到服务器本地,服务器上传图片到AWS3.后删除服务器本地的图片。
异步,从AWS3中获取图片,并下载到服务器本地。
把拿到的图片进行缩略图,后上传到AWS3.后删除服务器本地的图片
优点:异步处理缩略图。
缺点:上传过程,图片已经到达服务器本地了。但,又删除。为了达到压缩图的目的,从AWS3重新下载,后上传。资源浪费。
测试过程:
注释掉以下代码:图片压缩后,删除服务器本地的图片。
通过本地的http请求,上传6.8M的图片。
看服务器/tmp目录中 是否存在该图片?发现 原图6.8M,而/tmp目录中该图片才1.9M
猜测:网络不好的原因。
分析代码,curl中设置的timeout=15s 时间太短,延长为100s。
问题依旧。
总之,已经定位到了问题的关键!下载的原图有问题,导致压缩图不正常。
中间版本:优化思路
图片从AWS3中下载到服务器本地的过程,不使用curl命令/wget命令。————> 使用AWS3自身api实现文件下载
最终版本 待开发
不采用 以下方式:从AWS3中下载图片后,本地压缩,后压缩后的图片上传到AWS3
采用 以下方式:图片上传到AWS33后,直接在AWS的服务器上 实现图片压缩的功能。
==================最初版本 核心代码====================
String url = "http://p.upcdn.asiainfo.com/shitang/p/u/2017/11/10/222bc919-d0f1-445d-addf-23e68652b715.jpg";
String file = "/tmp/222bc919-d0f1-445d-addf-23e68652b715.jpg_8971304923840766083905.tmp";
curl --connect-timeout 100 -o + "file" + -s -w %{http_code} + "url"
wget -c -t 3 --timeout=60 -O "file" "url"
private String downPic(String url, String file) {
//取得当前JVM的运行时环境
Runtime rt = Runtime.getRuntime();
//Java代码中通过curl命令下载图片,并设置timeout时间:100s
Process p = rt.exec("curl --connect-timeout 100 -o " + file + " -s -w %{http_code} " + url);
int exitVal = p.waitFor();
System.out.println(exitVal == 0 ? "成功" : "失败");
StringBuilder sb = new StringBuilder();
InputStream inputStream = p.getInputStream();
int read;
while ((read = inputStream.read()) != -1) {
sb.append((char) read);
}
p.destroy();
rt.gc();
String httpCode = sb.toString();
}
拓展说明:
java.lang.Runtime.exec方法 作用:用于调用外部程序,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。
exec(String command) ,调用外部程序,入参command为外部可执行程序的启动路径或命令。
参考:《Java魔法堂:找外援的利器——Runtime.exec详解 https://www.cnblogs.com/fsjohnhuang/p/4081445.html》
参考:《Java Runtime.exec()的使用 https://www.cnblogs.com/mingforyou/p/3551199.html》
==================中间版本 核心代码====================
/*通过AWS的api下载图片*/
//bucketId = up-picture
//key = http://p.upcdn.asiainfo.com/shitang/p/u/2017/11/9/be610462-ca16-4512-9980-d0bc2932c98a.jpg
public S3Object getFile(String bucketId, String key) throws IOException {
key = key.shitangtsWith("/") ? key.substring(1) : key;
S3Object s3object = s3.getObject(new GetObjectRequest(bucketId, key));
return s3object;
}
//url = http://p.upcdn.asiainfo.com/shitang/p/u/2017/11/10/222bc919-d0f1-445d-addf-23e68652b715.jpg
//file = /tmp/222bc919-d0f1-445d-addf-23e68652b715.jpg_8971304923840766083905.tmp
private String downPic(String url, String file) {
String httpCode = "";
try {
String bucketId = storageService.getBucketId(UploadConstants.UPLOAD_FILE_PICTURE);
//示例:String key = "shitang/p/u/2017/11/9/222bc919-d0f1-445d-addf-23e68652b715.jpg";
String key = url.substring(url.indexOf("shitang"), url.length());
S3Object response = awsS3StorageService.getFile(bucketId, key);
// 输入流
InputStream is = response.getObjectContent();
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
OutputStream os = new FileOutputStream(new File(file));
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
httpCode = "200";
} catch (Exception e) {
log.info("exception", e);
}
return httpCode;
}
参考《http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/RetrievingObjectUsingJava.html》
===============最终版本:优化思路====================
待开发中....