需求:多商品主图上传
做法:因为是多商品多图上传,文件可能很大,所有让客户压缩成zip文件上传
1. controller层代码
package com.common.product.controller;
import com.common.commonutils.model.ResultResponse;
import com.common.commonutils.response.ResultCode;
import com.common.product.service.ZipService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* @author
*/
@Api(tags = "zip文件压缩")
@Slf4j
@RestController
@RequestMapping(value = "/zipProduct")
public class ZipProductController {
@Resource
private ZipService zipService;
@ApiOperation(value = "批量上传图片", response = ResultResponse.class)
@PostMapping(value = "/save")
public ResultResponse save(HttpServletRequest request) {
zipService.saveExecuteAsync(request);
return new ResultResponse(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
}
2. service层代码
package com.keyrus.product.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.utils.StringUtils;
import com.keyrus.commonutils.core.SnowflakeIdWorker;
import com.keyrus.product.entity.Image;
import com.keyrus.product.entity.ProductBasic;
import com.keyrus.product.entity.ProductLanguage;
import com.keyrus.product.mapper.ImageMapper;
import com.keyrus.product.mapper.ProductBasicMapper;
import com.keyrus.product.mapper.ProductLanguageMapper;
import com.keyrus.product.service.ZipService;
import com.keyrus.product.util.UrlUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Date;
import java.util.Map;
import java.util.zip.ZipFile;
/**
* @author longfei
*/
@Slf4j
@Service
public class ZipServiceImpl implements ZipService {
private static final int BUFFER_SIZE = 255;
@Resource
private UrlUnit urlUnit;
@Resource
private ProductBasicMapper productBasicMapper;
@Resource
private ProductLanguageMapper productLanguageMapper;
@Resource
private ImageMapper imageMapper;
@Override
@Async("asyncServiceExecutor") // 这里做的异步上传
public void saveExecuteAsync(HttpServletRequest request) {
// String language = request.getHeader("Accept-Language-Id");
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> multiFileMap = multipartRequest.getFileMap();
multiFileMap.values().forEach(x -> {
// urlUnit.getZipUrl():是nacos上配置的服务器路径
// 我本地测试的路径 D:/applog/product/zip
String url = urlUnit.getZipUrl() + x.getName();
try {
// 创建统一父文件夹
File file = new File(url);
if (!file.exists())
file.mkdirs();
// 把zip文件传输至服务器中
log.info("zipFileName:" + x.getName());
OutputStream outputStream = new FileOutputStream(url + "/" + x.getName() + ".zip");
outputStream.write(x.getBytes());
outputStream.flush();
outputStream.close();
// 解析zip
ZipFile zipFile = new ZipFile(new File(url + "/" + x.getName() + ".zip"));
zipFile.stream().forEach((entry) -> {
String fileName = entry.getName();
log.info("entryFileName:" + fileName);
if (entry.isDirectory()) { // 文件夹
File entryFile = new File(url + "/" + entry.getName());
if (!entryFile.exists())
entryFile.mkdirs();
log.info("创建文件夹:" + entryFile.getPath());
} else { // 是文件
// 可在此写自己的业务逻辑
// 图片写入至服务器
try {
OutputStream outputStreamImg = new FileOutputStream(url);
InputStream is = zipFile.getInputStream(entry);
int len;
byte[] buf = new byte[BUFFER_SIZE];
while ((len = is.read(buf)) != -1) {
outputStreamImg.write(buf, 0, len);
}
outputStreamImg.flush();
outputStreamImg.close();
is.close();
log.info("图片已导入服务器");
} catch (Exception e) {
log.error("zipImgMessage: " + e.getLocalizedMessage());
}
}
});
zipFile.close();
} catch (Exception e) {
log.info(e.getLocalizedMessage());
}
});
}
}
3. 业务逻辑(根据自己的业务自行书写)
String productCode = fileName.substring(fileName.lastIndexOf("/") + 1, fileName.indexOf("."));
log.info("productCode:" + productCode);
ProductBasic basic = productBasicMapper.selectByProductCode(productCode);
if (basic == null) {
return;
}
// 判断此语言下商品是否存在
log.info("basic: " + JSON.toJSONString(basic));
ProductLanguage productLanguage = productLanguageMapper.selectByBasicId(basic.getId(), language);
if (productLanguage == null) {
return;
}
log.info("language: " + JSON.toJSONString(productLanguage));
// 图片主键id
long id = SnowflakeIdWorker.getSnowflakeIdWorker().nextId();
// 图片地址 + 名称
String savePath = url + "/" + fileName.substring(0, fileName.lastIndexOf("/") + 1) + id + fileName.substring(fileName.indexOf("."));
log.info("savePath: " + savePath);
// 图片上传至服务器
try {
OutputStream outputStreamImg = new FileOutputStream(savePath);
InputStream is = zipFile.getInputStream(entry);
int len;
byte[] buf = new byte[BUFFER_SIZE];
while ((len = is.read(buf)) != -1) {
outputStreamImg.write(buf, 0, len);
}
outputStreamImg.flush();
outputStreamImg.close();
is.close();
log.info("图片已导入服务器");
} catch (Exception e) {
log.error("zipImgMessage: " + e.getLocalizedMessage());
}
// 商品图片数据库信息
Image image = new Image();
image.setId(id);
image.setLanguageId(productLanguage.getId());
image.setContainer(String.valueOf(image.getId()));
image.setSequence("0");
image.setIsDel(0);
image.setCreateTime(new Date());
image.setUpdateTime(new Date());
// 如果上传阿里云,可在此处写代码
image.setUrl(savePath);
imageMapper.insert(image);
4. 上传zip图片
5. 解析至服务器上
疑问:
- 这边是img4,而上传的那个是img2。之所以会这样,是因为我在postman测试的时候参数名称传的是img4,所有request解析出来之后是img4,联调的时候就看前端传过来的名称是什么了。
- 上面解压到服务器中的路径(url)是手动维护的,可以根据自己的需要调整解压后的文件样式