上传图片的两种方式
`
文章目录
前言
每个程序员貌似对上传图片都有一种执念,感觉一个项目有了上传图片上传文件的功能就很难,今天就给大家分享一下怎么上传图片,直接上干货
一、直接上传到项目jar包根目录
工具类的方法
java
/**
/**
* 获取上传路径
*/
public static String getUploadPath()
{
return getProfile() + "/upload";
}
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
Untils
java
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
return upload(baseDir, file, allowedExtension, false);
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param useCustomNaming 系统自定义文件名
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, boolean useCustomNaming)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" };
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb" };
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 编编码文件名(日期格式目录 + UUID + 后缀)
*/
public static final String uuidFilename(MultipartFile file)
{
return StringUtils.format("{}/{}.{}", DateUtils.datePath(), IdUtils.fastSimpleUUID(), getExtension(file));
}
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
/**
* 编码文件名(日期格式目录 + 原文件名 + 序列值 + 后缀)
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
二、上传到MinIo
搭建MinIo服务就跳过了,宝塔直接一分钟搭建,然后创建Bruck
Controller
java
/**
* 上传OSS对象存储
*
* @param file 文件
*/
@SaCheckPermission("system:oss:upload")
@Log(title = "OSS对象存储", businessType = BusinessType.INSERT)
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysOssUploadVo> upload(@RequestPart("file") MultipartFile file) {
if (ObjectUtil.isNull(file)) {
return R.fail("上传文件不能为空");
}
SysOssVo oss = ossService.upload(file);
SysOssUploadVo uploadVo = new SysOssUploadVo();
uploadVo.setUrl(oss.getUrl());
uploadVo.setFileName(oss.getOriginalName());
uploadVo.setOssId(oss.getOssId().toString());
return R.ok(uploadVo);
}
/**
* 下载OSS对象
*
* @param ossId OSS对象ID
*/
@SaCheckPermission("system:oss:download")
@GetMapping("/download/{ossId}")
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
ossService.download(ossId, response);
}
Service
java
@Override
public SysOssVo upload(MultipartFile file) {
String originalfileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
OssClient storage = OssFactory.instance();
UploadResult uploadResult;
try {
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
} catch (IOException e) {
throw new ServiceException(e.getMessage());
}
SysOssExt ext1 = new SysOssExt();
ext1.setFileSize(file.getSize());
ext1.setContentType(file.getContentType());
// 保存文件信息
return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1);
}
java
/**
* 上传 byte[] 数据到 Amazon S3,使用指定的后缀构造对象键。
*
* @param data 要上传的 byte[] 数据
* @param suffix 对象键的后缀
* @return UploadResult 包含上传后的文件信息
* @throws OssException 如果上传失败,抛出自定义异常
*/
public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), contentType);
}
java
public static final String SLASH = "/";
/**
* 上传 InputStream 到 Amazon S3
*
* @param inputStream 要上传的输入流
* @param key 在 Amazon S3 中的对象键
* @param length 输入流的长度
* @param contentType 文件内容类型
* @return UploadResult 包含上传后的文件信息
* @throws OssException 如果上传失败,抛出自定义异常
*/
public UploadResult upload(InputStream inputStream, String key, Long length, String contentType) {
// 如果输入流不是 ByteArrayInputStream,则将其读取为字节数组再创建 ByteArrayInputStream
if (!(inputStream instanceof ByteArrayInputStream)) {
inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
}
try {
// 创建异步请求体(length如果为空会报错)
BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder()
.contentLength(length)
.subscribeTimeout(Duration.ofSeconds(120))
.build();
// 使用 transferManager 进行上传
Upload upload = transferManager.upload(
x -> x.requestBody(body).addTransferListener(LoggingTransferListener.create())
.putObjectRequest(
y -> y.bucket(properties.getBucketName())
.key(key)
.contentType(contentType)
// 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同,
// 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置)
//.acl(getAccessPolicy().getObjectCannedACL())
.build())
.build());
// 将输入流写入请求体
body.writeInputStream(inputStream);
// 等待文件上传操作完成
CompletedUpload uploadResult = upload.completionFuture().join();
String eTag = uploadResult.response().eTag();
// 提取上传结果中的 ETag,并构建一个自定义的 UploadResult 对象
return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).eTag(eTag).build();
} catch (Exception e) {
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
}
}
java
@NotNull
private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult, SysOssExt ext1) {
SysOss oss = new SysOss();
oss.setUrl(uploadResult.getUrl());
oss.setFileSuffix(suffix);
oss.setFileName(uploadResult.getFilename());
oss.setOriginalName(originalfileName);
oss.setService(configKey);
oss.setExt1(JsonUtils.toJsonString(ext1));
baseMapper.insert(oss);
SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
return this.matchingUrl(sysOssVo);
}
java
package org.dromara.common.oss.factory;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.oss.constant.OssConstant;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.exception.OssException;
import org.dromara.common.oss.properties.OssProperties;
import org.dromara.common.redis.utils.CacheUtils;
import org.dromara.common.redis.utils.RedisUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* 文件上传Factory
*
* @author ZZW
*/
@Slf4j
public class OssFactory {
/**
* 全局 redis key (业务无关的key)
*/
String GLOBAL_REDIS_KEY = "global:";
/**
* 默认配置KEY
*/
String DEFAULT_CONFIG_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss:default_config";
private static final Map<String, OssClient> CLIENT_CACHE = new ConcurrentHashMap<>();
private static final ReentrantLock LOCK = new ReentrantLock();
/**
* 获取默认实例
*/
public static OssClient instance() {
// 获取redis 默认类型
String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY);
if (StringUtils.isEmpty(configKey)) {
throw new OssException("文件存储服务类型无法找到!");
}
return instance(configKey);
}
/**
* 根据类型获取实例
*/
public static OssClient instance(String configKey) {
String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey);
if (json == null) {
throw new OssException("系统异常, '" + configKey + "'配置信息不存在!");
}
OssProperties properties = JsonUtils.parseObject(json, OssProperties.class);
// 使用租户标识避免多个租户相同key实例覆盖
String key = configKey;
if (StringUtils.isNotBlank(properties.getTenantId())) {
key = properties.getTenantId() + ":" + configKey;
}
OssClient client = CLIENT_CACHE.get(key);
// 客户端不存在或配置不相同则重新构建
if (client == null || !client.checkPropertiesSame(properties)) {
LOCK.lock();
try {
client = CLIENT_CACHE.get(key);
if (client == null || !client.checkPropertiesSame(properties)) {
CLIENT_CACHE.put(key, new OssClient(configKey, properties));
log.info("创建OSS实例 key => {}", configKey);
return CLIENT_CACHE.get(key);
}
} finally {
LOCK.unlock();
}
}
return client;
}
}
java
@Override
public void init() {
List<SysOssConfig> list = baseMapper.selectList();
// 加载OSS初始化配置
for (SysOssConfig config : list) {
String configKey = config.getConfigKey();
if ("0".equals(config.getStatus())) {
RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
}
CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
}
}
java
package org.dromara.common.oss.constant;
import org.dromara.common.core.constant.GlobalConstants;
import java.util.Arrays;
import java.util.List;
/**
* 对象存储常量
*
* @author ZZW
*/
public interface OssConstant {
/**
* 默认配置KEY
*/
String DEFAULT_CONFIG_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss:default_config";
/**
* 预览列表资源开关Key
*/
String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
/**
* 系统数据ids
*/
List<Long> SYSTEM_DATA_IDS = Arrays.asList(1L, 2L, 3L, 4L);
/**
* 云服务商
*/
String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"};
/**
* https 状态
*/
String IS_HTTPS = "Y";
}