zhuguifei
2025-04-28 442928123f63ee497d766f9a7a14f0a6ee067e25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
 
package org.jeecg.modules.doc.component;
 
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.doc.vo.UploadFile;
import org.jeecg.modules.doc.vo.UploadFileResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
 
@Component
public abstract class Uploader {
    private static final Logger log = LoggerFactory.getLogger(Uploader.class);
    @Resource
    RedisLock redisLock;
    @Resource
    RedisUtil redisUtil;
 
    public Uploader() {
    }
 
    public List<UploadFileResult> upload(HttpServletRequest httpServletRequest) {
        UploadFile uploadFile = new UploadFile();
        uploadFile.setChunkNumber(1);
        uploadFile.setChunkSize(0L);
        uploadFile.setTotalChunks(1);
        uploadFile.setIdentifier(UUID.randomUUID().toString());
        List<UploadFileResult> uploadFileResultList = this.upload(httpServletRequest, uploadFile);
        return uploadFileResultList;
    }
 
    public List<UploadFileResult> upload(HttpServletRequest httpServletRequest, UploadFile uploadFile) {
        List<UploadFileResult> uploadFileResultList = new ArrayList();
        StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest)httpServletRequest;
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            throw new UploadException("未包含文件上传域");
        } else {
            try {
                Iterator<String> iter = request.getFileNames();
 
                while(iter.hasNext()) {
                    List<MultipartFile> multipartFileList = request.getFiles((String)iter.next());
                    Iterator var8 = multipartFileList.iterator();
 
                    while(var8.hasNext()) {
                        MultipartFile multipartFile = (MultipartFile)var8.next();
                        QiwenMultipartFile qiwenMultipartFile = new QiwenMultipartFile(multipartFile);
                        UploadFileResult uploadFileResult = this.doUploadFlow(qiwenMultipartFile, uploadFile);
                        uploadFileResultList.add(uploadFileResult);
                    }
                }
 
                return uploadFileResultList;
            } catch (Exception var12) {
                throw new UploadException(var12);
            }
        }
    }
 
    protected UploadFileResult doUploadFlow(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) {
        try {
            this.rectifier(qiwenMultipartFile, uploadFile);
            UploadFileResult uploadFileResult = this.organizationalResults(qiwenMultipartFile, uploadFile);
            return uploadFileResult;
        } catch (Exception var5) {
            throw new UploadException(var5);
        }
    }
 
    public abstract void cancelUpload(UploadFile uploadFile);
 
    protected abstract void doUploadFileChunk(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) throws IOException;
 
    protected abstract UploadFileResult organizationalResults(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile);
 
    private void rectifier(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) {
        String key = "QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":lock";
        String current_upload_chunk_number = "QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number";
        this.redisLock.lock(key);
 
        try {
            if (this.redisUtil.get(current_upload_chunk_number) == null) {
                this.redisUtil.set(current_upload_chunk_number, 1, 3600000L);
            }
 
            int currentUploadChunkNumber = Integer.parseInt((String)this.redisUtil.get(current_upload_chunk_number));
            if (uploadFile.getChunkNumber() != currentUploadChunkNumber) {
                this.redisLock.unlock(key);
                Thread.sleep(100L);
 
                while(this.redisLock.tryLock(key, 300L, TimeUnit.SECONDS)) {
                    currentUploadChunkNumber = Integer.parseInt((String)this.redisUtil.get(current_upload_chunk_number));
                    if (uploadFile.getChunkNumber() <= currentUploadChunkNumber) {
                        break;
                    }
 
                    if (Math.abs(currentUploadChunkNumber - uploadFile.getChunkNumber()) > 2) {
                        log.error("传入的切片数据异常,当前应上传切片为第{}块,传入的为第{}块。", currentUploadChunkNumber, uploadFile.getChunkNumber());
                        throw new UploadException("传入的切片数据异常");
                    }
 
                    this.redisLock.unlock(key);
                }
            }
 
            log.info("文件名{},正在上传第{}块, 共{}块>>>>>>>>>>", new Object[]{qiwenMultipartFile.getMultipartFile().getOriginalFilename(), uploadFile.getChunkNumber(), uploadFile.getTotalChunks()});
            if (uploadFile.getChunkNumber() == currentUploadChunkNumber) {
                this.doUploadFileChunk(qiwenMultipartFile, uploadFile);
                log.info("文件名{},第{}块上传成功", qiwenMultipartFile.getMultipartFile().getOriginalFilename(), uploadFile.getChunkNumber());
                this.redisUtil.getIncr("QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number");
            }
        } catch (Exception var9) {
            log.error("第{}块上传失败,自动重试", uploadFile.getChunkNumber());
            this.redisUtil.set("QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number", uploadFile.getChunkNumber(), 3600000L);
            throw new UploadException("更新远程文件出错", var9);
        } finally {
            this.redisLock.unlock(key);
        }
 
    }
 
    public synchronized boolean checkUploadStatus(UploadFile param, File confFile) throws IOException {
        RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");
 
        try {
            confAccessFile.setLength((long)param.getTotalChunks());
            confAccessFile.seek((long)(param.getChunkNumber() - 1));
            confAccessFile.write(127);
        } finally {
            IOUtils.closeQuietly(confAccessFile);
        }
 
        byte[] completeStatusList = FileUtils.readFileToByteArray(confFile);
 
        for(int i = 0; i < completeStatusList.length; ++i) {
            if (completeStatusList[i] != 127) {
                return false;
            }
        }
        if (param.getChunkNumber() < param.getTotalChunks()) {
            log.info("当前块号:{},总块号:{},文件id:{}", param.getChunkNumber(), param.getTotalChunks(),param.getIdentifier());
            return false;
        }
 
        confFile.delete();
        return true;
    }
 
    public void writeByteDataToFile(byte[] fileData, File file, UploadFile uploadFile) {
        RandomAccessFile raf = null;
 
        try {
            raf = new RandomAccessFile(file, "rw");
            FileChannel fileChannel = raf.getChannel();
            long position = (long)(uploadFile.getChunkNumber() - 1) * uploadFile.getChunkSize();
            fileChannel.position(position);
            fileChannel.write(ByteBuffer.wrap(fileData));
            fileChannel.force(true);
            fileChannel.close();
            raf.close();
        } catch (IOException var8) {
            throw new UploadException(var8);
        }
    }
}