工具类上传图片到阿里云 OSS 方法如下:
public class UploadOSSService implements Runnable{
public static final Logger LOGGER = Logger.getLogger(UploadOSSService.class);
private String orderId;
public String getOrderId() {
return orderId;
}
public void setOrderHeadId(String orderId) {
this.orderId = orderId;
}
@Override
public void run() {
try {
// redcoeByte 为图片二维码流,根据 orderId 查询获得
InputStream in = new ByteArrayInputStream(redcoeByte);
// 上传到OSS
String fileName = Md5Encrypt.md5(orderId.toString()) + ".png";
boolean ifSuccess = MFOSSClientUtil.uploadFile(fileName, in);
LOGGER.error("upload file to OSS is success or not: " + ifSuccess);
}catch(Exception e){
LOGGER.error("上传OSS失败*******: ", e);
}
}
}
上传下载工具类:
public class MFOSSClientUtil {
private static final Logger LOGGER = Logger.getLogger(CHOSSClientUtil.class);
/**
* 上传文件流到阿里云OSS
* @param filename
* @param input
* @return 是否上传成功
* @throws FileUploadException
* @throws SocketException
* @throws IOException
*/
public static boolean uploadFile(String filename,InputStream input) throws FileUploadException, SocketException, IOException{
boolean success = false;
// 上传到阿里云OSS
LOGGER.info("上传图片到阿里云OSS Started");
String bucketName = ProjectConfig.getOssBucketName();
OSSClient ossClient = initOSSClient();
try {
// 把字符串存入OSS,Object的名称为firstKey。详细请参看“SDK手册 > Java-SDK > 上传文件”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/upload_object.html?spm=5176.docoss/user_guide/upload_object
// InputStream is = new ByteArrayInputStream("Hello OSS".getBytes());
ossClient.putObject(bucketName, filename, input);
success = true;
System.out.println("Object:" + filename + "存入OSS成功。");
} catch (OSSException oe) {
oe.printStackTrace();
LOGGER.error("上传图片到阿里云OSS 失败: "+oe);
} catch (ClientException ce) {
ce.printStackTrace();
LOGGER.error("上传图片到阿里云OSS 失败: "+ce);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("上传图片到阿里云OSS 失败: "+e);
} finally {
ossClient.shutdown();
}
LOGGER.error("上传图片到阿里云OSS Completed");
return success;
}
/**
* 下载文件
*
* @param fileName
*/
public static void download(String fileName,OutputStream output) throws FileUploadException, SocketException, IOException{
LOGGER.error("Calling download...");
OSSClient ossClient = initOSSClient();
String bucketName = ProjectConfig.getOssBucketName();
try {
OSSObject ossObject = ossClient.getObject(bucketName, fileName);
InputStream inputStream = ossObject.getObjectContent();
try {
int bufSize = 1024 * 4;
byte[] buffer = new byte[bufSize];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
LOGGER.error("下载阿里云OSS 图片,读取 ossObject 数据流到 outputStream 失败:" + e);
e.printStackTrace();
}
} catch (Exception e) {
LOGGER.error("下载阿里云OSS 图片失败:" + e);
e.printStackTrace();
} finally {
ossClient.shutdown();
}
}
/**
* 初始化 OSSClient
* @return
* @throws SocketException
* @throws IOException
*/
public static OSSClient initOSSClient() throws SocketException, IOException
{
// OSS信息
String endpoint = "";
String accessKeyId = "";
String accessKeySecret = "";
String bucketName = "";
// 生成OSSClient,您可以指定一些参数,详见“SDK手册 > Java-SDK > 初始化”,
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/init.html?spm=5176.docoss/sdk/java-sdk/get-start
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
try {
// 判断Bucket是否存在。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
if (ossClient.doesBucketExist(bucketName)) {
System.out.println("您已经创建Bucket:" + bucketName + "。");
} else {
System.out.println("您的Bucket不存在,创建Bucket:" + bucketName + "。");
// 创建Bucket。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
ossClient.createBucket(bucketName);
}
} catch (OSSException oe) {
oe.printStackTrace();
LOGGER.error("初始化阿里云OSS 失败: "+oe);
} catch (ClientException ce) {
ce.printStackTrace();
LOGGER.error("初始化阿里云OSS 失败: "+ce);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("初始化阿里云OSS 失败:"+e);
}
return ossClient;
}
}
现在问题来了,当使用下面方法调用上传时,如果是批量上传,由于共用 uploadOSSService,可能造成 orderId 与上传的图片不匹配。单独上传就没问题。因为批量上传时候,有可能另外线程修改了 orderId ,但还没来得及修改图片流,就执行上传成功了。从而造成 orderId 和图片不对应。
解决方法是不要 Autowired UploadOSSService,而是每次调用的时候 new 一个新 UploadOSSService 对象。
@Autowired
private UploadOSSService uploadOSSService;
//上传到OSS。单独起线程处理
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
uploadOSSService.setOrderId(orderId);
fixedThreadPool.execute(uploadOSSService);
涉及多线程的时候,一定要异常小心。
网友评论