Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.channel.api.WxChannelBasicService;
import me.chanjar.weixin.channel.bean.address.AddressCodeResponse;
Expand All @@ -28,6 +27,7 @@
import me.chanjar.weixin.channel.util.ResponseUtils;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.RequestExecutor;

/**
Expand Down Expand Up @@ -76,12 +76,11 @@ public QualificationFileResponse uploadQualificationFile(File file) throws WxErr

@Override
public ChannelImageResponse getImg(String mediaId) throws WxErrorException {
String appId = shopService.getConfig().getAppid();
ChannelImageResponse rs;
try {
String url = GET_IMG_URL + "?media_id=" + mediaId;
RequestExecutor<ChannelImageResponse, String> executor = ChannelMediaDownloadRequestExecutor.create(shopService,
Files.createTempDirectory("wxjava-channel-" + appId).toFile());
FileUtils.getTmpDir());
rs = shopService.execute(executor, url, null);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* @author Daniel Qian
*/
public class FileUtils {
private static volatile File tmpDir;

/**
* 创建临时文件.
Expand All @@ -41,14 +42,39 @@ private static void copyToFile(final InputStream source, final File destination)
}

/**
* 创建临时文件.
* 创建临时文件,文件位于 {@link #getTmpDir()} 返回的目录中.
*
* @param inputStream 输入文件流
* @param name 文件名
* @param ext 扩展名
*/
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
return createTmpFile(inputStream, name, ext, Files.createTempDirectory("wxjava-temp").toFile());
return createTmpFile(inputStream, name, ext, getTmpDir());
}

/**
* 获取 SDK 共用的临时目录.
* <p>
* 目录在首次调用时创建,之后的调用都复用它,不会每次调用都新建一个永远不会被删除的临时目录;
* 目录被外部清理掉后,下次调用会重新创建。
* </p>
*
* @return 临时目录
* @throws IOException 无法创建临时目录时抛出
*/
public static File getTmpDir() throws IOException {
File dir = tmpDir;
if (dir == null || !dir.isDirectory()) {
synchronized (FileUtils.class) {
dir = tmpDir;
if (dir == null || !dir.isDirectory()) {
dir = Files.createTempDirectory("wxjava-temp").toFile();
dir.deleteOnExit();
tmpDir = dir;
}
}
}
return dir;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@ public void testCreateTmpFile() throws IOException {
public void testTestCreateTmpFile() {
}

@Test
public void testCreateTmpFileReusesOneTmpDir() throws IOException {
File first = FileUtils.createTmpFile(new ByteArrayInputStream("a".getBytes()), "first", "txt");
File second = FileUtils.createTmpFile(new ByteArrayInputStream("b".getBytes()), "second", "txt");
try {
// 每次调用都新建一个临时目录的话,调用方删除文件后目录仍会一直残留
assertThat(second.getParentFile()).isEqualTo(first.getParentFile());
} finally {
assertThat(first.delete()).isTrue();
assertThat(second.delete()).isTrue();
}
}

@Test
public void testGetTmpDirIsRecreatedAfterDeletion() throws IOException {
File tmpDir = FileUtils.getTmpDir();
assertThat(FileUtils.getTmpDir()).isEqualTo(tmpDir);

org.apache.commons.io.FileUtils.deleteDirectory(tmpDir);
assertThat(tmpDir).doesNotExist();

File recreated = FileUtils.getTmpDir();
assertThat(recreated).isDirectory();
File tmpFile = FileUtils.createTmpFile(new ByteArrayInputStream("c".getBytes()), "recreated", "txt");
assertThat(tmpFile.getParentFile()).isEqualTo(recreated);
assertThat(tmpFile.delete()).isTrue();
}

@Test
public void testImageToBase64ByStream() {
byte[] original = new byte[5000];
Expand Down
1 change: 1 addition & 0 deletions weixin-java-common/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<class name="me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateCheckerTest"/>
<class name="me.chanjar.weixin.common.session.SessionTest"/>
<class name="me.chanjar.weixin.common.util.http.ServerCertificateVerificationTest"/>
<class name="me.chanjar.weixin.common.util.fs.FileUtilsTest"/>
</classes>
</test>
</suite>
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,12 @@ public WxCpProductAlbumResult getProductAlbum(String productId) throws WxErrorEx
@Override
public WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer attachmentType,
InputStream inputStream) throws WxErrorException, IOException {
return uploadAttachment(mediaType, attachmentType, FileUtils.createTmpFile(inputStream,
UUID.randomUUID().toString(), fileType));
File tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType);
try {
return uploadAttachment(mediaType, attachmentType, tmpFile);
} finally {
tmpFile.delete();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ public class WxCpMediaServiceImpl implements WxCpMediaService {
@Override
public WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream)
throws WxErrorException, IOException {
return this.upload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
File tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType);
try {
return this.upload(mediaType, tmpFile);
} finally {
tmpFile.delete();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ public class WxCpTpMediaServiceImpl implements WxCpTpMediaService {
@Override
public WxMediaUploadResult upload(String mediaType, String fileType, InputStream inputStream, String corpId)
throws WxErrorException, IOException {
return this.upload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType), corpId);
File tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType);
try {
return this.upload(mediaType, tmpFile, corpId);
} finally {
tmpFile.delete();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package me.chanjar.weixin.cp.api.impl;

import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import me.chanjar.weixin.cp.tp.service.impl.WxCpTpMediaServiceImpl;
import org.testng.annotations.Test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;

/**
* 验证通过输入流上传时,SDK 内部创建的临时文件在上传后被删除.
*/
public class WxCpTmpFileCleanupTest {

@Test
public void mediaUploadFromStreamDeletesTmpFile() throws Exception {
WxCpMediaServiceImpl mediaService = spy(new WxCpMediaServiceImpl(mock(WxCpService.class)));
WxMediaUploadResult result = new WxMediaUploadResult();
List<File> uploaded = new ArrayList<>();
doAnswer(invocation -> {
File file = invocation.getArgument(1);
assertTrue(file.isFile());
uploaded.add(file);
return result;
}).when(mediaService).upload(eq("image"), any(File.class));

assertSame(mediaService.upload("image", "jpg", new ByteArrayInputStream(new byte[]{1, 2, 3})), result);

assertEquals(uploaded.size(), 1);
assertFalse(uploaded.get(0).exists());
}

@Test
public void tpMediaUploadFromStreamDeletesTmpFile() throws Exception {
WxCpTpMediaServiceImpl mediaService = spy(new WxCpTpMediaServiceImpl(mock(WxCpTpService.class)));
WxMediaUploadResult result = new WxMediaUploadResult();
List<File> uploaded = new ArrayList<>();
doAnswer(invocation -> {
File file = invocation.getArgument(1);
assertTrue(file.isFile());
uploaded.add(file);
return result;
}).when(mediaService).upload(eq("image"), any(File.class), eq("CORP_ID"));

assertSame(mediaService.upload("image", "jpg", new ByteArrayInputStream(new byte[]{1, 2, 3}), "CORP_ID"),
result);

assertEquals(uploaded.size(), 1);
assertFalse(uploaded.get(0).exists());
}

@Test
public void externalContactAttachmentFromStreamDeletesTmpFile() throws Exception {
WxCpExternalContactServiceImpl contactService = spy(new WxCpExternalContactServiceImpl(mock(WxCpService.class)));
WxMediaUploadResult result = new WxMediaUploadResult();
List<File> uploaded = new ArrayList<>();
doAnswer(invocation -> {
File file = invocation.getArgument(2);
assertTrue(file.isFile());
uploaded.add(file);
return result;
}).when(contactService).uploadAttachment(eq("image"), eq(1), any(File.class));

assertSame(contactService.uploadAttachment("image", "jpg", 1, new ByteArrayInputStream(new byte[]{1, 2, 3})),
result);

assertEquals(uploaded.size(), 1);
assertFalse(uploaded.get(0).exists());
}
}
1 change: 1 addition & 0 deletions weixin-java-cp/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<class name="me.chanjar.weixin.cp.tp.service.impl.WxCpTpMessageServiceImplTest"/>
<class name="me.chanjar.weixin.cp.api.impl.BaseWxCpServiceImplLogTest"/>
<class name="me.chanjar.weixin.cp.api.impl.WxCpIntelligentRobotApiModeServiceTest"/>
<class name="me.chanjar.weixin.cp.api.impl.WxCpTmpFileCleanupTest"/>
</classes>
</test>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.json.GsonHelper;
Expand Down Expand Up @@ -42,11 +43,10 @@ public void commit(WxMaCodeCommitRequest commitRequest) throws WxErrorException

@Override
public byte[] getQrCode(String path) throws WxErrorException {
String appId = this.service.getWxMaConfig().getAppid();
Path qrCodeFilePath = null;
try {
RequestExecutor<File, String> executor = BaseMediaDownloadRequestExecutor
.create(this.service.getRequestHttp(), Files.createTempDirectory("wxjava-ma-" + appId).toFile());
.create(this.service.getRequestHttp(), FileUtils.getTmpDir());

final StringBuilder url = new StringBuilder(GET_QRCODE_URL);
if (StringUtils.isNotBlank(path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,16 @@ public String uploadResponseImage(File imageFile) throws WxErrorException, IOExc

@Override
public String uploadResponseImage(InputStream inputStream, String fileName) throws WxErrorException, IOException {
File tmpFile = null;
try {
return this.uploadResponseImage(FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileName));
tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileName);
return this.uploadResponseImage(tmpFile);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
} finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.UUID;

import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Media.MEDIA_GET_URL;
Expand All @@ -29,10 +28,16 @@ public class WxMaMediaServiceImpl implements WxMaMediaService {

@Override
public WxMediaUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException {
File tmpFile = null;
try {
return this.uploadMedia(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
tmpFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType);
return this.uploadMedia(mediaType, tmpFile);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
} finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
}

Expand All @@ -48,7 +53,7 @@ public WxMediaUploadResult uploadMedia(String mediaType, File file) throws WxErr
public File getMedia(String mediaId) throws WxErrorException {
try {
RequestExecutor<File, String> executor = BaseMediaDownloadRequestExecutor
.create(this.wxMaService.getRequestHttp(), Files.createTempDirectory("wxma").toFile());
.create(this.wxMaService.getRequestHttp(), FileUtils.getTmpDir());
return this.wxMaService.execute(executor, MEDIA_GET_URL, "media_id=" + mediaId);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
Expand Down
Loading