Kaynağa Gözat

Merge branch 'featrue/图片批量上传和批量上架0907' of qng/kmall-pt into master

图片批量上传和批量上架
钱能归 3 yıl önce
ebeveyn
işleme
f13494e74e

+ 5 - 0
kmall-admin/pom.xml

@@ -32,6 +32,11 @@
             <artifactId>kmall-api</artifactId>
             <version>${kmall-version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.ant</groupId>
+            <artifactId>ant</artifactId>
+            <version>1.9.7</version>
+        </dependency>
 
     </dependencies>
 

+ 241 - 7
kmall-admin/src/main/java/com/kmall/admin/controller/GoodsController.java

@@ -1,28 +1,37 @@
 package com.kmall.admin.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.kmall.admin.dto.GoodsDetailsDto;
 import com.kmall.admin.dto.GoodsDto;
 import com.kmall.admin.entity.GoodsEntity;
 import com.kmall.admin.entity.GoodsGalleryEntity;
-import com.kmall.admin.entity.StoreEntity;
-import com.kmall.admin.service.GoodsGalleryService;
-import com.kmall.admin.service.GoodsService;
-import com.kmall.admin.service.OfflineCartService;
-import com.kmall.admin.service.StoreService;
+import com.kmall.admin.entity.SysOssEntity;
+import com.kmall.admin.service.*;
 import com.kmall.admin.utils.ParamUtils;
 import com.kmall.admin.utils.ShiroUtils;
+import com.kmall.api.cache.UserTokenCache;
+import com.kmall.common.utils.ImgException;
 import com.kmall.common.constant.Dict;
 import com.kmall.common.constant.JxlsXmlTemplateName;
 import com.kmall.admin.fromcomm.entity.SysUserEntity;
+import com.kmall.common.fileserver.util.FileManager;
 import com.kmall.common.utils.*;
 import com.kmall.common.utils.excel.ExcelUtil;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.*;
 import java.util.*;
+import org.apache.tools.zip.ZipEntry;
+import org.apache.tools.zip.ZipFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 /**
  * Controller
@@ -34,6 +43,8 @@ import java.util.*;
 @RestController
 @RequestMapping("goods")
 public class GoodsController {
+
+    private static Log logger = LogFactory.getLog(UserTokenCache.class);
     @Autowired
     private GoodsService goodsService;
     @Autowired
@@ -44,7 +55,8 @@ public class GoodsController {
     private ExcelUtil excelUtil;
     @Autowired
     private StoreService storeService;
-
+    @Autowired
+    private SysOssService sysOssService;
     /**
      * 查看列表
      */
@@ -300,6 +312,228 @@ public class GoodsController {
         return R.ok().put("goodsDetails", goods);
     }
 
+    @RequestMapping("/generalGoodsImgUploadByZip")
+    @ResponseBody
+    public R batchAddImgByZip(@RequestParam("file") MultipartFile file) throws IOException {
+        //上传文件
+        batchAdd(file,2);
+        return R.ok();
+    }
+
+    @RequestMapping("/generalGoodsImgUpload")
+    @ResponseBody
+    public R batchAddImg(@RequestParam("file") MultipartFile file) throws IOException {
+        //上传文件
+        batchAdd(file,1);
+        return R.ok();
+    }
+
+    private Map<String, Object> batchAdd(MultipartFile file, int type) throws IOException {
+        /*
+         *创建临时文件夹
+         * 解压文件
+         */
+        String fileName = file.getOriginalFilename();
+        String path = "/data/project/img/";
+        File dir = new File(path);
+        dir.mkdirs();
+        String filePath = "/data/project/img2/";
+        File fileDir = new File(filePath);
+        fileDir.mkdirs();
+        File saveFile = new File(fileDir, fileName);//将压缩包解析到指定位置
+        List<String>list = new ArrayList<>();
+
+        try {
+            file.transferTo(saveFile);
+            String newFilePath = filePath + fileName;
+            File zipFile = new File(newFilePath);
+            unZipFiles(zipFile, path,list,type);//解压文件,获取文件路径
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.out.println("解压执行失败");
+            throw e;
+        }
+
+
+        logger.info(JSON.toJSONString(list));
+        //程序结束时,删除临时文件
+        deleteFiles(filePath);//删除压缩包文件夹
+        deleteFiles(path);//删除解压文件夹**
+
+        Map<String, Object> jsonMap = new HashMap<String, Object>();
+        jsonMap.put("ret",list);
+        return jsonMap;
+    }
+
+    public void deleteFiles(String filePath) {
+        File file = new File(filePath);
+        if ((!file.exists()) || (!file.isDirectory())) {
+            System.out.println("file not exist");
+            return;
+        }
+        String[] tempList = file.list();
+        File temp = null;
+        for (int i = 0; i < tempList.length; i++) {
+            if (filePath.endsWith(File.separator)) {
+                temp = new File(filePath + tempList[i]);
+            }
+            else {
+                temp = new File(filePath + File.separator + tempList[i]);
+            }
+            if (temp.isFile()) {
+                temp.delete();
+            }
+            if (temp.isDirectory()) {
+                this.deleteFiles(filePath + "/" + tempList[i]);
+            }
+        }
+        // 空文件的删除
+        file.delete();
+    }
+
+    public void unZipFiles(File srcFile, String destDirPath, List<String> list, int type) throws RuntimeException {
+        long start = System.currentTimeMillis();
+        // 判断源文件是否存在
+        if (!srcFile.exists()) {
+            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
+        }
+        // 开始解压
+        ZipFile zipFile = null;
+        try {
+            zipFile = new ZipFile(srcFile);
+        } catch (IOException e) {
+            throw new RRException("zip文件解压出错", e);
+        }
+        zipFile.getEncoding();
+        Enumeration<?> entries = zipFile.getEntries();
+        List<ZipEntry> entryList = new ArrayList<>();
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = (ZipEntry) entries.nextElement();
+            logger.info("解压" + entry.getName());
+            entryList.add(entry);
+            // 如果是文件夹,就创建个文件夹
+        }
+        if(null==entryList){
+            throw new RRException("文件夹内无图片信息,请检查后重试");
+        }
+        if(entryList.size()>30){
+            throw new RRException("最多上传30张图片");
+        }
+        try {
+            for(ZipEntry entry : entryList){
+                if (entry.isDirectory()) {
+                    String dirPath = destDirPath + "/" + entry.getName();
+                    File dir = new File(dirPath);
+                    dir.mkdirs();
+                } else {
+                    // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
+                    File targetFile = new File(destDirPath + "/" + entry.getName());
+                    // 保证这个文件的父文件夹必须要存在
+
+                    if(!targetFile.getParentFile().exists()){
+
+                    }
+                    targetFile.createNewFile();
+                    // 将压缩文件内容写入到这个文件中
+                    InputStream is = zipFile.getInputStream(entry);
+                    FileOutputStream fos = new FileOutputStream(targetFile);
+                    int len;
+                    byte[] buf = new byte[1024];
+                    while ((len = is.read(buf)) != -1) {
+                        fos.write(buf, 0, len);
+                    }
+
+                    MultipartFile mulFileByPath = getMulFileByPath(destDirPath + "/" + entry.getName());
+                    long fileSize = mulFileByPath.getSize();
+                    int maxSize = 1 * 1024 * 1024;
+                    if (fileSize > maxSize) {
+                        throw new RRException("商品图片过大(最大1M),请检查!");
+                    }
+//                    String imgg = entry.getName().split("\\.")[1];
+//                    if (!"jpg".equals(imgg)&&!"jpeg".equals(imgg)) {
+//                        throw new RRException("图片格式不正确,请检查!");
+//                    }
+
+                    //上传文件
+                    String url = FileManager.upload(mulFileByPath);
+                    list.add(url);
+                    if(type == 1){
+                        String sku = entry.getName().split("\\.")[0];
+                        if (null==sku||"".equals(sku)) {
+                            throw new ImgException("文件为:" + sku + "的商品命名格式不正确,请检查!");
+                        }
+                        GoodsEntity goodsEntity = goodsService.queryBySku(sku);
+                        goodsEntity.setPrimaryPicUrl(url);
+                        goodsEntity.setListPicUrl(url);
+                        goodsService.updateForImgUrl(goodsEntity);
+                    }else if(type == 2){
+                        String barCode = entry.getName().split("/")[1];
+                        GoodsEntity goodsEntity = goodsService.queryByBarcode(barCode);
+                        goodsEntity.setPrimaryPicUrl(url);
+                        goodsEntity.setListPicUrl(url);
+                        goodsService.updateForImgUrl(goodsEntity);
+                    }
+                    //保存文件信息
+                    SysOssEntity ossEntity = new SysOssEntity();
+                    ossEntity.setUrl(url);
+                    ossEntity.setCreateDate(new Date());
+                    sysOssService.save(ossEntity);
+                    // 关流顺序,先打开的后关闭
+                    fos.close();
+                    is.close();
+                }
+            }
+            long end = System.currentTimeMillis();
+            System.out.println("解压完成,耗时:" + (end - start) +" ms");
+        }catch (RRException e) {
+            throw new RRException(e.getMessage(), e);
+        }catch (Exception e) {
+            throw new RuntimeException("unzip error from ZipUtils", e);
+        } finally {
+            if(zipFile != null){
+                try {
+                    zipFile.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private static MultipartFile getMulFileByPath(String picPath) {
+        FileItem fileItem = createFileItem(picPath);
+        MultipartFile mfile = new CommonsMultipartFile(fileItem);
+        return mfile;
+    }
 
+    private static FileItem createFileItem(String filePath)
+    {
+        FileItemFactory factory = new DiskFileItemFactory(16, null);
+        String textFieldName = "textField";
+        int num = filePath.lastIndexOf(".");
+        String extFile = filePath.substring(num);
+        FileItem item = factory.createItem(textFieldName, "text/plain", true,
+                "MyFileName" + extFile);
+        File newfile = new File(filePath);
+        int bytesRead = 0;
+        byte[] buffer = new byte[8192];
+        try
+        {
+            FileInputStream fis = new FileInputStream(newfile);
+            OutputStream os = item.getOutputStream();
+            while ((bytesRead = fis.read(buffer, 0, 8192))
+                    != -1)
+            {
+                os.write(buffer, 0, bytesRead);
+            }
+            os.close();
+            fis.close();
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return item;
+    }
 
 }

+ 4 - 0
kmall-admin/src/main/java/com/kmall/admin/dao/GoodsDao.java

@@ -31,4 +31,8 @@ public interface GoodsDao extends BaseDao<GoodsEntity> {
     GoodsEntity queryObjectByStoreId(@Param("id") Long id, @Param("storeId") Long storeId);
 
     GoodsEntity queryGoodsByGoodsSnAndStoreId(@Param("goodsSn") String goodsSn, @Param("storeId") Long storeId);
+
+    GoodsEntity queryByBarcode(String barCode);
+
+    GoodsEntity queryBySku(String sku);
 }

+ 16 - 0
kmall-admin/src/main/java/com/kmall/admin/service/GoodsService.java

@@ -131,4 +131,20 @@ public interface GoodsService {
      * @return
      */
     GoodsDetailsDto queryGoodsDetailsByProdBarcode(String prodBarcode);
+
+    /**
+     * 根据条形码查询商品
+     * @param barCode
+     * @return
+     */
+    GoodsEntity queryByBarcode(String barCode);
+
+    /**
+     * 根据sku查询商品
+     * @param sku
+     * @return
+     */
+    GoodsEntity queryBySku(String sku);
+
+    void updateForImgUrl(GoodsEntity goodsEntity);
 }

+ 31 - 0
kmall-admin/src/main/java/com/kmall/admin/service/impl/GoodsServiceImpl.java

@@ -1073,4 +1073,35 @@ public class GoodsServiceImpl implements GoodsService {
     public GoodsEntity queryObjectBySn(String goodsSn) {
         return goodsDao.queryObjectBySn(goodsSn);
     }
+
+
+
+    /**
+     * 根据条形码查询商品
+     *
+     * @param barCode
+     * @return
+     */
+    @Override
+    public GoodsEntity queryByBarcode(String barCode) {
+        return goodsDao.queryByBarcode(barCode);
+    }
+
+    /**
+     * 根据sku查询商品
+     *
+     * @param sku
+     * @return
+     */
+    @Override
+    public GoodsEntity queryBySku(String sku) {
+        return goodsDao.queryBySku(sku);
+    }
+
+    @Transactional
+    @Override
+    public void updateForImgUrl(GoodsEntity goodsEntity){
+        // 修改商品
+        goodsDao.update(goodsEntity);
+    }
 }

+ 2 - 2
kmall-admin/src/main/resources/conf/fastdfs.properties

@@ -9,7 +9,7 @@ base_path=/data/files/
 
 #tracker server\u662FFastDFS\u6587\u4EF6\u7CFB\u7EDF\u7684\u534F\u8C03\u8005,\u5176\u4E3B\u8981\u4F5C\u7528\u662F\u8D1F\u8F7D\u5747\u8861\u548C\u8C03\u5EA6\u3002
 #Tracker server\u5728\u5185\u5B58\u4E2D\u8BB0\u5F55\u5206\u7EC4\u548CStorage server\u7684\u72B6\u6001\u7B49\u4FE1\u606F\uFF0C\u4E0D\u8BB0\u5F55\u6587\u4EF6\u7D22\u5F15\u4FE1\u606F
-tracker_server=192.168.1.251:22122
+tracker_server=183.3.221.143:22122
 
 log_level=info
 
@@ -24,7 +24,7 @@ use_storage_id = false
 storage_ids_filename = storage_ids.conf
 
 #HTTP \u670D\u52A1\u5668\u5730\u5740
-http.tracket_nginx_addr=192.168.1.251
+http.tracket_nginx_addr=183.3.221.143
 
 #HTTP \u670D\u52A1\u5668\u7AEF\u53E3\u53F7
 http.tracker_server_port=80

+ 13 - 0
kmall-admin/src/main/resources/mybatis/mapper/GoodsDao.xml

@@ -580,4 +580,17 @@
     <select id="queryMaxId" resultType="java.lang.Long" parameterType="map">
         SELECT MAX(id) FROM mall_goods
     </select>
+
+    <select id="queryByBarcode" resultType="com.kmall.admin.entity.GoodsEntity">
+        select *
+        from mall_goods
+        where prod_barcode = #{barCode}
+    </select>
+
+    <select id="queryBySku" resultType="com.kmall.admin.entity.GoodsEntity">
+        select *
+        from mall_goods
+        where sku = #{sku}
+    </select>
+
 </mapper>

+ 17 - 0
kmall-admin/src/main/webapp/WEB-INF/page/shop/goods.html

@@ -138,11 +138,28 @@
                         <i-button type="ghost" icon="ios-cloud-upload-outline">普货商品导入</i-button>
                     </Upload>
                 </i-col>
+                <i-col style="display: inline-grid;">
+                    <Upload :show-upload-list="false" :on-success="uploadExcelSuccess" :on-error="uploadExcelError" :on-format-error="uploadExcelFormatError"
+                            :on-progress="uploadExcelProgress"
+                            :format="['xls','xlsx','zip']"
+                            action="../goods/generalGoodsImgUpload">
+                        <i-button type="ghost" icon="ios-cloud-upload-outline">商品图片批量导入(图片不能超过1M,最多30张)</i-button>
+                    </Upload>
+                </i-col>
+<!--                <i-col style="display: inline-grid;">-->
+<!--                    <Upload :show-upload-list="false" :on-success="uploadExcelSuccess" :on-error="uploadExcelError" :on-format-error="uploadExcelFormatError"-->
+<!--                            :on-progress="uploadExcelProgress"-->
+<!--                            :format="['xls','xlsx','zip']"-->
+<!--                            action="../goods/generalGoodsImgUploadByZip">-->
+<!--                        <i-button type="ghost" icon="ios-cloud-upload-outline">商品图片(文件夹)批量导入</i-button>-->
+<!--                    </Upload>-->
+<!--                </i-col>-->
                 #end
                 #if($shiro.hasPermission("goods:down"))
                 &nbsp;&nbsp;&nbsp;&nbsp;
                 <a href="../statics/file/goods_export_yyyy_mm_dd_v1.0.0.xls">商品模板下载</a>&nbsp;&nbsp;&nbsp;&nbsp;
                 <a href="../statics/file/general_goods_export_yyyy_mm_dd_v1.0.0.xls">普货商品模板下载</a>
+                <a href="../statics/file/goods_img.zip">商品图片批量导入示例下载</a>
                 #end
             </div>
         </Row>

+ 13 - 0
kmall-admin/src/main/webapp/js/shop/goods.js

@@ -106,6 +106,7 @@ $(function () {
 });
 
 var ztree;
+var exportMsg;
 
 var setting = {
     data: {
@@ -592,6 +593,18 @@ var vm = new Vue({
                 desc: '文件 ' + file.name + ' 格式不正确,请上传 xls 或 xlsx 格式的文件。'
             });
         },
+        uploadExcelProgress:function(event, file, fileList){
+            console.log("上传中")
+            console.log(event)
+            console.log(file)
+            console.log(fileList)
+            console.log("上传中")
+            exportMsg = this.$Message.loading({
+                content: 'Loading...',
+                duration: 0
+            });
+            setTimeout(exportMsg,1000);
+        },
         handleRemove(file) {
             // 从 upload 实例删除数据
             const fileList = vm.uploadList;

BIN
kmall-admin/src/main/webapp/statics/file/goods_img.zip


+ 51 - 0
kmall-common/src/main/java/com/kmall/common/utils/ImgException.java

@@ -0,0 +1,51 @@
+package com.kmall.common.utils;
+
+/**
+ * 自定义异常
+ */
+public class ImgException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    private String msg;
+    private int code = 500;
+
+    public ImgException(String msg) {
+        super(msg);
+        this.msg = msg;
+    }
+
+    public ImgException(String msg, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+    }
+
+    public ImgException(String msg, int code) {
+        super(msg);
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public ImgException(String msg, int code, Throwable e) {
+        super(msg, e);
+        this.msg = msg;
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+
+}

+ 5 - 5
kmall-manager/src/main/resources/conf/redis.properties

@@ -1,11 +1,11 @@
-########## redis 配置 ##########
+########## redis \u914D\u7F6E ##########
 
 # [dev, prod]
 redis.env = dev
 
-# 开发环境
+# \u5F00\u53D1\u73AF\u5883
 redis.dev.keyPrefix=platform
-redis.dev.host=127.0.0.1
+redis.dev.host=183.3.221.143
 redis.dev.port=6379
 redis.dev.pool.maxIdle=200
 redis.dev.pool.maxWait=1000
@@ -13,7 +13,7 @@ redis.dev.pool.maxTotal=10000
 redis.dev.pool.testOnBorrow=true
 
 
-# 中网生产环境
+# \u4E2D\u7F51\u751F\u4EA7\u73AF\u5883
 redis.prod.keyPrefix=platform
 redis.prod.host=172.18.132.30
 redis.prod.port=6379
@@ -22,7 +22,7 @@ redis.prod.pool.maxWait=1000
 redis.prod.pool.maxTotal=10000
 redis.prod.pool.testOnBorrow=true
 
-## 中网国际生产环境
+## \u4E2D\u7F51\u56FD\u9645\u751F\u4EA7\u73AF\u5883
 #redis.prod.keyPrefix=platform
 #redis.prod.host=183.62.225.124
 #redis.prod.port=6379