前言
对于简单word文档的生成导出,java已经有着很多技术来进行处理,在有着相对固定的格式样板下,采用word模板导出相对会是比较好的选择。但是当数据量且包含大量图片后,采用模板导出就显得无力了,模板的缺点是无法应对动态复杂的数据文档生成,这时候采用动态生成word是唯一的选择。
问题背景:需要生成一个包含大量图片表格的word文档,该文档内容在百兆与1G中间
可以看到该模板是一个相当复杂的文件,既需要对不同类型的图片设置不同的格式还需要动态生成每个类型表格的位置,并将图片插入的word文件当中去
代码处理
controller:
package com.wlh.zetc.restore.controller;import com.wlh.zetc.common.core.util.R;
import com.wlh.zetc.restore.manage.LedgerSequenceManage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 台账生成** @author wanghailin* @date 2024-05-23 14:19:56*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/restoreLedger" )
@Tag(description = "restoreLedger" , name = "台账生成" )
//@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class LedgerSequenceController {private final LedgerSequenceManage ledgerSequenceManage;/*** 通过乡镇id来生成台账* @param regionId* @return R*/@Operation(summary = "通过乡镇id来生成台账" , description = "通过乡镇id来生成台账" )@GetMapping("/{regionId}" )
// @PreAuthorize("@pms.hasPermission('zetc_ledger_generate')" )public R getById(@PathVariable("regionId" ) Long regionId) {//log.info("Request thread=>start");System.out.println("Request thread=>start");ledgerSequenceManage.generateAndUpload(regionId);//Log.info("Request thread=>end");System.out.println("Request thread=>end");return R.ok("台账生成中,请稍后到台账中心下载最新文档");}
}
Manage:
package com.wlh.zetc.restore.manage;import cn.hutool.core.date.DateUtil;
import com.wlh.zetc.common.data.tenant.TenantContextHolder;
import com.wlh.zetc.common.security.util.SecurityUtils;
import com.wlh.zetc.restore.bo.SubRegionBO;
import com.wlh.zetc.restore.entity.Activity;
import com.wlh.zetc.restore.entity.RestoreFileEntity;
import com.wlh.zetc.restore.entity.RestoreRegionEntity;
import com.wlh.zetc.restore.enums.LedgerTypeEnum;
import com.wlh.zetc.restore.service.*;
import com.wlh.zetc.restore.service.impl.QiniuServiceImpl;
import com.wlh.zetc.restore.utils.FormatProcessToWordUtils;
import com.wlh.zetc.restore.utils.StrategicChoicesUtils;
import com.wlh.zetc.restore.utils.TextUtils;
import lombok.AllArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;/*** 至农台账导出顺序梳理管理** @author wanghailin* @date 2024-05-8 15:49:33*/
@Service
@AllArgsConstructor
public class LedgerSequenceManage {private final RestoreFileService fileService;private final RestoreInStoreService inStoreService;private final RestoreMatterService matterService;private final RestoreOutStoreService outStoreService;private final RestorePatrolTaskService patrolTaskService;private final RestoreUsePlanService usePlanService;private final List<List<Activity>> activities;private final RestoreRegionService regionService;private final StrategicChoicesUtils strategicChoicesUtils;private final FormatProcessToWordUtils formatProcessToWordUtils;private final QiniuServiceImpl qiniuService;//通过乡镇id,来给所在乡镇下的村数据排序public List<List<Activity>> sequence(Long regionId,String streetTown){//清空数据收集池中的数据strategicChoicesUtils.reset();//1.根据乡镇id拿到该乡镇的名称//2.拿到该乡镇下所有的村id(分为2种情况)//2.1 村id集合String groupSubRegionId = regionService.getGroupSubRegionId(regionId);//2.2 村id单独List<SubRegionBO> subRegionList = regionService.getSubRegionId(regionId);//乡镇为单位//发货单(照片)List<Activity> materialDeliveryData = fileService.getMaterialDeliveryData(groupSubRegionId);//物资到货(照片)List<Activity> inStoreData = inStoreService.getInStoreData(groupSubRegionId);//控地巡视(照片)List<Activity> patrolLandData = patrolTaskService.getPatrolLandData(groupSubRegionId);//旱地种植结构调整照片List<Activity> apsdData = fileService.getAPSDData(groupSubRegionId);//产品照片List<Activity> productData = fileService.getProductData(groupSubRegionId);//会议照片List<Activity> meetData = fileService.getMeetData(groupSubRegionId);//喷施路径照片List<Activity> sprayPathData = usePlanService.getSprayPathData(groupSubRegionId);//数据汇集strategicChoicesUtils.collect(materialDeliveryData).collect(inStoreData).collect(patrolLandData).collect(apsdData).collect(productData).collect(meetData).collect(sprayPathData);//村为单位//出库、施工、回收subRegionList.forEach(subRegion -> {//用于村分隔处理List<Activity> villageSeparation = new ArrayList<>();Activity village = new Activity();village.setRegionName(subRegion.getRegionName());village.setSeparateFlag(true);villageSeparation.add(village);strategicChoicesUtils.collect(villageSeparation);List<String> matterNameList = matterService.getMatterName(Long.valueOf(subRegion.getRegionId()));if (!matterNameList.isEmpty()) {matterNameList.forEach(matterName -> {//出库(照片)List<Activity> outStoreData = outStoreService.getOutStoreData(subRegion.getRegionId(), matterName);//施工过程(照片)List<Activity> usePlanData = usePlanService.getUsePlanData(subRegion.getRegionId(), matterName);//包装袋回收(照片)(需签名)List<Activity> packBackData = usePlanService.getPackBackData(subRegion.getRegionId(), matterName);strategicChoicesUtils.collect(outStoreData).collect(usePlanData).collect(packBackData);});}//水分管理(照片)List<Activity> patrolWaterData = patrolTaskService.getPatrolWaterData(subRegion.getRegionId());strategicChoicesUtils.collect(patrolWaterData);});//自定义规制处理器return strategicChoicesUtils.handle(strategicChoicesUtils.getCollectedListActivities(),streetTown);}//异步调用该方法生成并上传文档@Asyncpublic void generateAndUpload(Long regionId){try {
// Log.info("Ledger generation thread => start");System.out.println("Ledger generation thread => start");RestoreRegionEntity region = regionService.getById(regionId);String streetTown = region.getRegionName();List<List<Activity>> sequence = sequence(regionId,streetTown);InputStream inputStream = formatProcessToWordUtils.exportActivitiesToWord(sequence);// 上传到服务器String filename = streetTown + DateUtil.today() +"-"+ System.currentTimeMillis()/1000+".docx";String project = "ledger"+ TenantContextHolder.getTenantId()+"/";String key = project+ TextUtils.generateFileName(filename);// 上传完后的伪地址String pseudoAddress = qiniuService.uploadImage2qiniu(inputStream, key);strategicChoicesUtils.reset();// 获取到的地址保存在数据库表中,以供后续下载(放在文件表中使用不同类型区分)RestoreFileEntity wordFile = new RestoreFileEntity();wordFile.setRegionId(regionId);wordFile.setFileUrl(pseudoAddress);wordFile.setFileType(LedgerTypeEnum.LEDGER.getType());wordFile.setFileUse(LedgerTypeEnum.LEDGER.getUse());wordFile.setFileSuffix(LedgerTypeEnum.LEDGER.getSuffix());
// wordFile.setCreateBy(SecurityUtils.getUser().getUsername());wordFile.setCreateBy("test");fileService.save(wordFile);
// Log.info("Ledger generation thread => end");System.out.println("Ledger generation thread => end");} catch (Exception e) {e.printStackTrace();}}}
Util:
package com.wlh.zetc.restore.utils;import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.wlh.zetc.restore.entity.Activity;
import com.wlh.zetc.restore.enums.GenerateTypeEnum;
import com.wlh.zetc.restore.service.impl.QiniuServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHeight;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.springframework.stereotype.Service;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigInteger;
import java.util.List;
/*** 至农台账生成工具类** @author wanghailin* @date 2024-05-18 10:49:33*/
@Service
@AllArgsConstructor
public class FormatProcessToWordUtils {private final QiniuServiceImpl qiniuService;public InputStream exportActivitiesToWord(List<List<Activity>> activities) throws Exception {InputStream inputStream = null;try (XWPFDocument document = new XWPFDocument()) {for (int activityListIndex = 0; activityListIndex < activities.size(); activityListIndex++) {for (int activityIndex = 0; activityIndex < activities.get(activityListIndex).size(); activityIndex++) {Activity activity = activities.get(activityListIndex).get(activityIndex);if(activity.getSeparateFlag() != null && activity.getSeparateFlag()){if(StringUtils.isNotEmpty(activity.getRegionName())){for (char ch : activity.getRegionName().toCharArray()) {XWPFParagraph paragraph = document.createParagraph();paragraph.setAlignment(ParagraphAlignment.CENTER); // 设置段落居中XWPFRun run = paragraph.createRun();run.setText(String.valueOf(ch)); // 设置文本为当前字符run.setBold(true); // 设置加粗run.setFontFamily("宋体"); // 设置字体为宋体run.setFontSize(72); // 设置字体大小为72号// 换行,每个字一行if (ch != activity.getRegionName().charAt(activity.getRegionName().length() - 1)) {run.addBreak();}}}// 在内容后添加分页符XWPFParagraph breakParagraph = document.createParagraph();XWPFRun breakRun = breakParagraph.createRun();breakRun.addBreak(BreakType.PAGE);}// 标题仅在第一个Activity中添加if (activityIndex == 0) {XWPFParagraph titleParagraph = document.createParagraph();titleParagraph.setAlignment(ParagraphAlignment.CENTER);XWPFRun titleRun = titleParagraph.createRun();titleRun.setText(activity.getTitle());titleRun.setBold(true);titleRun.setFontFamily("宋体");titleRun.setFontSize(22); // 二号字体大约是22pt}if (activity != null && activity.getType() != null){if(!activity.getType().equals(GenerateTypeEnum.PATROL.getCode())|| !activity.getType().equals(GenerateTypeEnum.DELIVERY.getCode())){// 次标题XWPFParagraph subTitleParagraph = document.createParagraph();subTitleParagraph.setAlignment(ParagraphAlignment.CENTER);XWPFRun subTitleRun = subTitleParagraph.createRun();subTitleRun.setText(getCircleNumber(activityIndex + 1)); // 使用圆圈数字编号subTitleRun.setBold(true);subTitleRun.setFontFamily("宋体");subTitleRun.setFontSize(22);}}//发货单 1*n 表格if (activity != null && activity.getType() != null) {if (activity.getType().equals(GenerateTypeEnum.DELIVERY.getCode())) {// 表格List<String> urls = activity.getUrls(); // 图片URL列表int rows = 0;if (urls != null && urls.size() > 0) {rows = urls.size(); // n行,每个URL一个单元格}XWPFTable table = document.createTable(rows, 1); // 创建n*1的表格// 设置表格宽度CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();width.setType(STTblWidth.DXA);width.setW(BigInteger.valueOf(8500)); // 将宽度设置为原来的两倍,大约30.06厘米try (CloseableHttpClient httpClient = HttpClients.createDefault()) {if (urls != null && urls.size() > 0) {// 填充表格数据并设置单元格宽度for (int i = 0; i < urls.size(); i++) {XWPFTableRow row = table.getRow(i); // 获取当前行XWPFTableCell cell = row.getCell(0); // 获取行中的唯一单元格cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);XWPFParagraph cellParagraph = cell.getParagraphs().get(0);cellParagraph.setAlignment(ParagraphAlignment.CENTER);XWPFRun run = cellParagraph.createRun();run.setBold(true); // 设置文本加粗// 设置单元格高度CTTrPr trpr = row.getCtRow().isSetTrPr() ? row.getCtRow().getTrPr() : row.getCtRow().addNewTrPr();CTHeight ht = trpr.sizeOfTrHeightArray() > 0 ? trpr.getTrHeightArray(0) : trpr.addNewTrHeight();if (StringUtils.isNotEmpty(activity.getTitle()) && i <= 2) {ht.setVal(BigInteger.valueOf(6350)); // 设置行高为11.2厘米对应的DXA单位} else {ht.setVal(BigInteger.valueOf(6550)); // 设置行高为12厘米对应的DXA单位}download(run, httpClient, urls.get(i), activity.getType()); // 假设download方法用于处理图片下载和显示}}} catch (IOException e) {e.printStackTrace();}} else {// 表格List<String> urls = activity.getUrls(); // 图片URL列表int rows = 0;if (urls != null && urls.size() > 0) {rows = (int) Math.ceil(urls.size() / 2.0);}XWPFTable table = document.createTable(rows, 2);// 设置表格宽度CTTblWidth width = table.getCTTbl().addNewTblPr().addNewTblW();width.setType(STTblWidth.DXA);width.setW(BigInteger.valueOf(8500)); // 大约15.03厘米try (CloseableHttpClient httpClient = HttpClients.createDefault()) {if (urls != null && urls.size() > 0) {// 填充表格数据并设置单元格高度for (int i = 0; i < urls.size(); i++) {int rowIndex = i / 2;int colIndex = i % 2;XWPFTableRow row = table.getRow(rowIndex);// 确保行有足够的单元格while (row.getTableCells().size() <= colIndex) {row.createCell();}XWPFTableCell cell = row.getCell(colIndex);cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);XWPFParagraph cellParagraph = cell.getParagraphs().get(0);cellParagraph.setAlignment(ParagraphAlignment.CENTER);XWPFRun run = cellParagraph.createRun();run.setBold(true); // 设置文本加粗// 设置单元格高度CTTrPr trpr = row.getCtRow().isSetTrPr() ? row.getCtRow().getTrPr() : row.getCtRow().addNewTrPr();CTHeight ht = trpr.sizeOfTrHeightArray() > 0 ? trpr.getTrHeightArray(0) : trpr.addNewTrHeight();if (StringUtils.isNotEmpty(activity.getTitle()) && i <= 4) {ht.setVal(BigInteger.valueOf(6350)); // 设置行高为11.2厘米对应的DXA单位} else {ht.setVal(BigInteger.valueOf(6550)); // 设置行高为12厘米对应的DXA单位}download(run, httpClient, urls.get(i), activity.getType());}}} catch (IOException e) {e.printStackTrace();}}}// 在每个Activity处理完毕后添加分页符XWPFParagraph breakParagraph = document.createParagraph();XWPFRun breakRun = breakParagraph.createRun();breakRun.addBreak(BreakType.PAGE);}}// 保存Word文件到InputStreamByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();try {document.write(byteArrayOutputStream);} finally {byteArrayOutputStream.close();}// 创建InputStreaminputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());}return inputStream;}/*** 根据序列号生成对应的带圈数字。* @param number 序列号(1到10)* @return 带圈数字的字符串表示,如果序列号超出范围,则返回null。*/public String getCircleNumber(int number) {if (number < 1 || number > 10) {return null; // 序列号超出范围}return String.valueOf((char) ('\u2460' + number - 1));}/*** 根据url下载图片*/public void download(XWPFRun run, CloseableHttpClient httpClient, String url,Integer type) throws UnsupportedEncodingException {// 下载并插入图片// 拼接出可以访问下载得七牛云图片地址String downloadUrl = qiniuService.getPrivateDownloadUrl(url);HttpGet httpGet = new HttpGet(downloadUrl);try (CloseableHttpResponse response = httpClient.execute(httpGet)) {if (response.getStatusLine().getStatusCode() == 200) {// 将图片内容缓存到内存中ByteArrayOutputStream baos = new ByteArrayOutputStream();response.getEntity().writeTo(baos);byte[] imageBytes = baos.toByteArray();// 从缓存的数据创建一个新的ByteArrayInputStream用于读取图片尺寸InputStream sizeStream = new ByteArrayInputStream(imageBytes);BufferedImage image = ImageIO.read(sizeStream);double originalWidth = image.getWidth();double originalHeight = image.getHeight();double aspectRatio = originalHeight / originalWidth;Integer width = 200;// 根据宽度和宽高比计算高度if (type.equals(GenerateTypeEnum.DELIVERY.getCode())){width = width * 2;}double widthEmus = Units.toEMU(width); // 设定的宽度,单位为EMUdouble heightEmus = widthEmus * aspectRatio; // 根据宽高比计算的高度,单位为EMUif(heightEmus > 5000000.0){heightEmus = heightEmus * 0.75;}// 从缓存的数据创建一个新的ByteArrayInputStream用于插入图片InputStream insertStream = new ByteArrayInputStream(imageBytes);// 插入图片run.addPicture(insertStream, XWPFDocument.PICTURE_TYPE_JPEG, url, (int) widthEmus, (int) heightEmus);}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (InvalidFormatException e) {e.printStackTrace();}}
}
Util:
package com.wlh.zetc.restore.utils;import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.wlh.zetc.restore.entity.Activity;
import com.wlh.zetc.restore.enums.PatrolPatrolTypeEnum;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** 至农台账生成决策数据处理*/
@Service
public class StrategicChoicesUtils {private static final List<List<Activity>> activities = new ArrayList<>();// 收集需要生成的activitypublic StrategicChoicesUtils collect(List<Activity> activityList) {if (activityList != null && !activityList.isEmpty()) {activities.add(new ArrayList<>(activityList));}return this; // 返回当前对象以支持链式调用}public List<List<Activity>> handle(List<List<Activity>> activitiesList,String streetTown) {for (List<Activity> activities : activitiesList) {for (Activity activity : activities) {if (activity.getType() != null) {String title = getTitleBasedOnType(activity,streetTown);activity.setTitle(title);}}}return activitiesList; // 返回处理后的List<List<Activity>>}private String getTitleBasedOnType(Activity activity,String streetTown) {String title = "";String regionName = StringUtils.isNotEmpty(activity.getRegionName()) ? activity.getRegionName() : "";String matterName = StringUtils.isNotEmpty(activity.getMatterName()) ? activity.getMatterName() : "";String date = StringUtils.isNotEmpty(activity.getDate()) ? activity.getDate() + "-" : "";switch (activity.getType()) {case 1: // DELIVERY(1,"发货单"),title = streetTown + regionName + "物资发货单";break;case 2: // ARRIVAL(2,"到货"),title = streetTown + regionName + matterName + "到货";break;case 3: // PATROL(3,"巡视"),String patrolTypeDesc = getPatrolTypeDesc(activity.getPatrolType());title = streetTown + date + patrolTypeDesc + "巡视";break;case 4: // APSD(4,"旱地种植结构调整"),title = "旱地种植结构调整情况";break;case 5: // PRODUCT(5,"产品"),title = matterName + "产品";break;case 6: // MEET(6,"会议"),title = "会议照片";break;case 7: // ROUTE(7,"喷施路径"),title = streetTown + matterName + "喷施路径";break;case 8: // OUTBOUND(8,"出库"),title = streetTown + regionName + matterName + "出库";break;case 9: // SPRINKLE(9,"施工过程"),title = streetTown + regionName + matterName + "施工过程";break;case 10: // RECOVERY(10,"包装袋回收"),title = streetTown + regionName + "包装袋回收";break;case 11: // water(11,"水分管理"),title = streetTown + regionName + "水分管理";break;case 0: // OTHER(0,"其它")title = "其它";break;}return title;}private String getPatrolTypeDesc(Integer patrolType) {if (patrolType == null) return "";switch (patrolType) {case 1: return PatrolPatrolTypeEnum.WATER.getDesc();case 2: return PatrolPatrolTypeEnum.CONTROL.getDesc();case 3: return PatrolPatrolTypeEnum.FLIGHT.getDesc();case 4: return PatrolPatrolTypeEnum.SPRINKLING.getDesc();case 5: return PatrolPatrolTypeEnum.OTHER.getDesc();default: return "";}}// 获取累积后的Activity列表public List<Activity> getCollectedActivities() {return activities.stream().flatMap(List::stream) // 将List<List<Activity>>转换为Stream<Activity>.collect(Collectors.toList()); // 将Stream<Activity>收集到List中}// 获取累积后的List<Activity>public List<List<Activity>> getCollectedListActivities() {return activities;}// 重置activities列表,以便重新开始收集public StrategicChoicesUtils reset() {activities.clear();return this;}
}
七牛云文件上传
maven:
<!-- 七牛云sdk --><dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.7.0</version></dependency><!-- 图片信息获取 --><dependency><groupId>com.drewnoakes</groupId><artifactId>metadata-extractor</artifactId><version>2.18.0</version></dependency>
yml:
oss:qiniu:domain: qiniu.znkj0215.com # 访问域名(正式访问域名地址) 暂未配置https
# domain: qiniu.iswhl.com # 访问域名(测试访问域名地址) 已配置httpsaccessKey: APlM_0fW1A_PRS5bQ92rdGf9oSW-5q9mZK3Tv6yk # 公钥secretKey: Ri2eN9h4htBjZa8J8n_7QBfsAAvM_Arz5_CLqWth # 私钥bucketName: zhinonggengdi #存储空间名称
service:
package com.wlh.zetc.restore.service;import java.io.InputStream;
import java.io.UnsupportedEncodingException;/*** 七牛文件存储** @author wanghailin* @date 2024-03-12 10:21:35*/
public interface QiniuService {String uploadImage2qiniu(InputStream in, String key);boolean deleteImageFromQiniu(String key);String getPrivateDownloadUrl(String fileName) throws UnsupportedEncodingException;}
impl:
package com.wlh.zetc.restore.service.impl;import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.*;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.wlh.zetc.restore.properties.QiniuProperties;
import com.wlh.zetc.restore.service.QiniuService;
import com.wlh.zetc.restore.utils.TextUtils;
import io.netty.channel.unix.Unix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;/*** 七牛文件存储** @author wanghailin* @date 2024-03-12 10:21:35*/
@Service
public class QiniuServiceImpl implements QiniuService
{private final String domain;private final String bucketName;private final String ak;private final String sk;// 七牛文件上传管理器private final Configuration cfg;private final Auth auth;@Autowiredpublic QiniuServiceImpl(QiniuProperties oss){this.ak = oss.getAccessKey();this.sk = oss.getSecretKey();this.domain = oss.getDomain(); // CDN域名this.bucketName = oss.getBucketName();// //构造一个带指定 Region 对象的配置类cfg = new Configuration(Zone.zone0());auth = Auth.create(ak,sk);}/*** 上传图片到七牛云* @return 图片url* */@Overridepublic String uploadImage2qiniu(InputStream in, String key){try {UploadManager uploadManager = new UploadManager(cfg);// 根据命名空间生成的上传tokenString upToken = auth.uploadToken(bucketName);Response response = uploadManager.put(in,key,upToken,null, null);//解析上传成功的结果DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);//System.out.println(putRet.key);//System.out.println(putRet.hash);//return String.format("http://%s/%s",this.domain,putRet.key);return putRet.key;} catch (QiniuException ex) {Response r = ex.response;System.err.println(r.toString());try {System.err.println(r.bodyString());} catch (QiniuException ex2) {//ignore}}return null;}/*** 删除图片* */@Overridepublic boolean deleteImageFromQiniu(String imageUrl){BucketManager bucketManager = new BucketManager(auth, cfg);try {String key= TextUtils.getKey(imageUrl);Response response = bucketManager.delete(bucketName,key);return response.isOK();} catch (QiniuException ex) {//如果遇到异常,说明删除失败System.err.println(ex.code());System.err.println(ex.response.toString());}return false;}/*** 获取文件下载路径** @param fileName* @return* @throws UnsupportedEncodingException*/public String getPrivateDownloadUrl(String fileName) throws UnsupportedEncodingException {//文件https访问配置DownloadUrl url = new DownloadUrl(domain, true, fileName);//DownloadUrl url = new DownloadUrl(domain, false, fileName);long expireInSeconds = 3600;//1小时,可以自定义链接过期时间long deadline = System.currentTimeMillis()/1000 + expireInSeconds;Auth auth = Auth.create(ak, sk);String urlString = null;try {urlString = url.buildURL(auth, deadline);} catch (QiniuException e) {throw new RuntimeException(e);}return urlString;}
}
导出效果
空白部分是因为数据缺失