文件上传--2021/12/27
Controller
/**
* 文件上传
* @param file 上传的文件
* @param request
* @return 返回结果
* @author guozh
* @date 2021/12/27 9:37
*/
@PostMapping("/uploadUpgradeFile")
public CommonResponse uploadUpgradeFile(MultipartFile file,HttpServletRequest request){
CommonResponse instance = CommonResponse.getInstance();
String companyId = HttpUtil.getCompanyId(request);
try {
String fileUrl = deviceService.uploadUpgradeFile(companyId,file); //文件路径
instance.setResultData(fileUrl);
}catch (BusinessException businessException){ //捕获自定义异常
instance.setErrorCode(businessException.getCode());
instance.setErrorMessage(businessException.getMessage());
}catch (IOException ioException){
instance.setErrorCode(10000);
instance.setErrorMessage(ioException.getMessage());
}
return instance;
}
自定义异常
package cn.iovnet.commons.exception;
import cn.iovnet.commons.utils.util.MessagesUtil;
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
public BusinessException(Integer code, String message) {
this.code = code;
this.message = message;
}
public BusinessException(Integer code) {
super(MessagesUtil.getMessage(code));
this.code = code;
}
public BusinessException(Integer code, String... args) {
super(MessagesUtil.getMessage(code, args));
this.code = code;
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Integer code, Throwable cause) {
super(MessagesUtil.getMessage(code), cause);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
ServiceImpl
@Override
public String uploadUpgradeFile(String companyId, MultipartFile file) throws IOException {
String filename = file.getOriginalFilename(); //文件全名
String substring = filename.substring(filename.indexOf(".") + 1); //截取后缀
String fileUrl;
if (substring.equals("txt")){
// TODO
fileUrl = DdyScheduleConstants.FILE_PATH + companyId + "/" + filename;
// String upload = AliossUtil.upload("", file.getInputStream());
} else {
throw new BusinessException(1,"文件类型不匹配");
}
return fileUrl;
}
调用的upload方法
/**
* 阿里oss 上传
*
* @param fileUrl 文件地址 如 2019-10-11/example/example.txt 会自动创建路径
* @param input 上传文件流
* @return 上传之后的文件地址
*/
public static String upload(String fileUrl, InputStream input) {
OSS ossClient = initOssClient();
try {
PutObjectResult result = ossClient.putObject(new PutObjectRequest(OssConstants.bucketName, fileUrl, input));
ossClient.shutdown();
if (null != result) {
logger.info("upload success. oss url: {}", fileUrl);
return fileUrl;
}
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "";
}
public static String upload(String fileUrl, File file) {
OSS ossClient = initOssClient();
PutObjectResult result = ossClient.putObject(new PutObjectRequest(OssConstants.bucketName, fileUrl, file));
ossClient.shutdown();
if (null != result) {
logger.info("upload success. oss url: {}", fileUrl);
return fileUrl;
}
return "";
}
常量路径
/**
* 文件上传路径
*/
public static final String FILE_PATH = "/xxx/yyy-file/";
Alioss工具类
public class AliossUtil {
private static final Logger logger = LoggerFactory.getLogger(AliossUtil.class);
private static final Map<String, AppendUpload> APPEND_UPLOAD_CACHE_MAP = new ConcurrentHashMap<>();
private AliossUtil() {
}
/**
* 阿里oss 拷贝文件
*
* @param source 源地址
* @param target 目标地址
* @return 上传之后的文件地址
*/
public static String copy(String source, String target) {
OSS ossClient = initOssClient();
CopyObjectResult result = ossClient.copyObject(OssConstants.bucketName, source, OssConstants.bucketName, target);
ossClient.shutdown();
if (null != result) {
logger.info("copy success. oss url: {}", target);
return target;
}
return "";
}
/**
* 阿里云oss大文件上传
* @param fileUrl
* @param file
* @return
*/
public static boolean multipartUpload(String fileUrl, MultipartFile file) {
boolean result = false;
OSS ossClient = initOssClient();
try {
// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(OssConstants.bucketName, fileUrl);
// 如果需要在初始化分片时设置文件存储类型,请参考以下示例代码。
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
request.setObjectMetadata(metadata);
// 初始化分片。
InitiateMultipartUploadResult upResult = ossClient.initiateMultipartUpload(request);
// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。
String uploadId = upResult.getUploadId();
// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
List<PartETag> partETags = new ArrayList<PartETag>();
// 每个分片的大小,用于计算文件有多少个分片。单位为字节。//1 MB。
final long partSize = 1 * 1024 * 1024L;
long fileLength = file.getSize();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// 遍历分片上传。
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
InputStream input = file.getInputStream();
// 跳过已经上传的分片。
input.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(OssConstants.bucketName);
uploadPartRequest.setKey(fileUrl);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(input);
// 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。
uploadPartRequest.setPartSize(curPartSize);
// 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。
uploadPartRequest.setPartNumber( i + 1);
// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
// 每次上传分片之后,OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
partETags.add(uploadPartResult.getPartETag());
}
// 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(OssConstants.bucketName, fileUrl, uploadId, partETags);
// 如果需要在完成文件上传的同时设置文件访问权限,请参考以下示例代码。
// completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead);
// 完成上传。
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
logger.info(completeMultipartUploadResult.getETag());
result = true;
} catch (Exception e) {
logger.error("文件上传失败 {}", e);
} finally {
// 关闭OSSClient。
ossClient.shutdown();
}
return result;
}
/**
* 阿里oss 上传
*
* @param fileUrl 文件地址 如 2019-10-11/example/example.txt 会自动创建路径
* @param input 上传文件流
* @return 上传之后的文件地址
*/
public static String upload(String fileUrl, InputStream input) {
OSS ossClient = initOssClient();
try {
PutObjectResult result = ossClient.putObject(new PutObjectRequest(OssConstants.bucketName, fileUrl, input));
ossClient.shutdown();
if (null != result) {
logger.info("upload success. oss url: {}", fileUrl);
return fileUrl;
}
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "";
}
public static String upload(String fileUrl, File file) {
OSS ossClient = initOssClient();
PutObjectResult result = ossClient.putObject(new PutObjectRequest(OssConstants.bucketName, fileUrl, file));
ossClient.shutdown();
if (null != result) {
logger.info("upload success. oss url: {}", fileUrl);
return fileUrl;
}
return "";
}
public static String appendUpload(String fileUrl, InputStream input, Boolean isEnd) {
if (!APPEND_UPLOAD_CACHE_MAP.containsKey(fileUrl)) {
OSS ossClient = new OSSClientBuilder().build(OssConstants.endpoint, OssConstants.keyId, OssConstants.keySecret);
// ObjectMetadata meta = new ObjectMetadata();
// meta.setContentType("text/plain");
AppendObjectRequest appendObjectRequest = new AppendObjectRequest(OssConstants.bucketName, fileUrl, input);
appendObjectRequest.setPosition(0L);
AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
AppendUpload appendUpload = new AppendUpload();
appendUpload.setOssClient(ossClient);
appendUpload.setAppendObjectRequest(appendObjectRequest);
appendUpload.setAppendObjectResult(appendObjectResult);
APPEND_UPLOAD_CACHE_MAP.put(fileUrl, appendUpload);
} else {
AppendUpload appendUpload = APPEND_UPLOAD_CACHE_MAP.get(fileUrl);
OSS ossClient = appendUpload.getOssClient();
AppendObjectResult appendObjectResult = appendUpload.getAppendObjectResult();
AppendObjectRequest appendObjectRequest = appendUpload.getAppendObjectRequest();
appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(input);
appendObjectResult = ossClient.appendObject(appendObjectRequest);
appendUpload.setAppendObjectResult(appendObjectResult);
}
if (isEnd) {
AppendUpload appendUpload = APPEND_UPLOAD_CACHE_MAP.get(fileUrl);
OSS ossClient = appendUpload.getOssClient();
ossClient.shutdown();
APPEND_UPLOAD_CACHE_MAP.remove(fileUrl);
}
return fileUrl;
}
private static OSS initOssClient() {
OSS ossClient = new OSSClientBuilder().build(OssConstants.endpoint, OssConstants.keyId, OssConstants.keySecret);
ossClient.setBucketAcl(OssConstants.bucketName, CannedAccessControlList.PublicRead);
// 如果不存在bucket 创建bucket
if (!ossClient.doesBucketExist(OssConstants.bucketName)) {
ossClient.createBucket(OssConstants.bucketName);
CreateBucketRequest createBucketRequest = new CreateBucketRequest(OssConstants.bucketName);
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
ossClient.createBucket(createBucketRequest);
}
return ossClient;
}
/**
* @description: 流式下载
* @param objectName 例: gps_record/cloud-bus/153/2019-11/2019-11-12.txt
* @return: java.util.List<java.lang.String>
*/
public static List<String> downloadFile(String objectName) {
List<String> list = new ArrayList<>();
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(OssConstants.endpoint, OssConstants.keyId, OssConstants.keySecret);
try {
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
OSSObject ossObject = ossClient.getObject(OssConstants.bucketName, objectName);
// 读取文件内容。
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
list.add(line);
}
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
reader.close();
} catch (OSSException e) {
logger.error("下载文件失败,{},{}", e.getErrorCode(), e.getErrorMessage());
} catch (IOException e) {
logger.error("下载文件失败,{}", e.getMessage());
} finally {
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
return list;
}
/**
* 单个文件下载
* @param objectName 文件路径
* @return org.springframework.http.ResponseEntity<byte[]>
*/
public static ResponseEntity<byte[]> downloadFileToStream(String objectName) {
InputStream inputStream = null;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(OssConstants.endpoint, OssConstants.keyId, OssConstants.keySecret);
try {
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
OSSObject ossObject = ossClient.getObject(OssConstants.bucketName, objectName);
// 读取文件内容
inputStream = ossObject.getObjectContent();
//设置头信息
HttpHeaders headers = new HttpHeaders();
//设置响应的文件名
String downloadFileName = objectName.substring(objectName.lastIndexOf("/") + 1);
headers.setContentDispositionFormData("attachment", downloadFileName);
headers.add("Access-Control-Expose-Headers", "filename");
headers.add("filename", downloadFileName);
//application/octet-stream二进制流数据的形式下载
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
assert inputStream != null;
byte[] bytes = inputStream.readAllBytes();
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (OSSException e) {
logger.error("下载文件失败,{},{}", e.getErrorCode(), e.getErrorMessage());
} catch (IOException e) {
logger.error("下载文件失败,{}", e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}
/**
* 批量下载文件(以zip压缩包的形式存储)
* @param objectNameList 文件路径(在OSS上存储的全路径)
* @param saveFileName 文件保存名称(带后缀名)
* @return org.springframework.http.ResponseEntity<byte[]>
*/
public static ResponseEntity<byte[]> downloadFileToZip(List<String> objectNameList, String saveFileName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(OssConstants.endpoint, OssConstants.keyId, OssConstants.keySecret);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(byteArrayOutputStream);
try {
for (String objectName : objectNameList) {
String fileName = objectName.substring(objectName.lastIndexOf("/") + 1);
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
OSSObject ossObject = ossClient.getObject(OssConstants.bucketName, objectName);
// 读取文件内容
InputStream inputStream = ossObject.getObjectContent();
ZipEntry zipEntry = new ZipEntry(fileName);
zipOut.putNextEntry(zipEntry);
zipOut.write(inputStream.readAllBytes());
zipOut.closeEntry();
}
//设置头信息
HttpHeaders headers = new HttpHeaders();
//设置响应的文件名
String fileName = new String(saveFileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
headers.setContentDispositionFormData("attachment", fileName);
headers.add("Access-Control-Expose-Headers", "filename");
headers.add("filename", fileName);
//application/octet-stream二进制流数据的形式下载
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
byte[] bytes = byteArrayOutputStream.toByteArray();
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
zipOut.close();
} catch (IOException e) {
e.printStackTrace();
}
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}
}