All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dromara.hutool.http.multipart.UploadFile Maven / Gradle / Ivy

There is a newer version: 6.0.0.M3
Show newest version
/*
 * Copyright (c) 2013-2024 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dromara.hutool.http.multipart;

import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.text.StrUtil;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.NoSuchFileException;

/**
 * 上传的文件对象
 *
 * @author Looly
 */
public class UploadFile {

	private static final String TMP_FILE_PREFIX = "hutool-";
	private static final String TMP_FILE_SUFFIX = ".upload.tmp";

	private final UploadFileHeader header;
	private final UploadSetting setting;

	private long size = -1;

	// 文件流(小文件位于内存中)
	private byte[] data;
	// 临时文件(大文件位于临时文件夹中)
	private File tempFile;

	/**
	 * 构造
	 *
	 * @param header  头部信息
	 * @param setting 上传设置
	 */
	public UploadFile(final UploadFileHeader header, final UploadSetting setting) {
		this.header = header;
		this.setting = setting;
	}

	// ---------------------------------------------------------------- operations

	/**
	 * 从磁盘或者内存中删除这个文件
	 */
	public void delete() {
		if (tempFile != null) {
			//noinspection ResultOfMethodCallIgnored
			tempFile.delete();
		}
		if (data != null) {
			data = null;
		}
	}

	/**
	 * 将上传的文件写入指定的目标文件路径,自动创建文件
* 写入后原临时文件会被删除 * * @param destPath 目标文件路径 * @return 目标文件 * @throws IOException IO异常 */ public File write(final String destPath) throws IOException { if (data != null || tempFile != null) { return write(FileUtil.file(destPath)); } return null; } /** * 将上传的文件写入目标文件
* 写入后原临时文件会被删除 * * @param destination 目标文件 * @return 目标文件 * @throws IOException IO异常 */ public File write(File destination) throws IOException { assertValid(); if (destination.isDirectory()) { destination = new File(destination, this.header.getFileName()); } if (data != null) { // 内存中 FileUtil.writeBytes(data, destination); data = null; } else { // 临时文件 if(null == this.tempFile){ throw new NullPointerException("Temp file is null !"); } if(!this.tempFile.exists()){ throw new NoSuchFileException("Temp file: [" + this.tempFile.getAbsolutePath() + "] not exist!"); } FileUtil.move(tempFile, destination, true); } return destination; } /** * @return 获得文件字节流 * @throws IOException IO异常 */ public byte[] getFileContent() throws IOException { assertValid(); if (data != null) { return data; } if (tempFile != null) { return FileUtil.readBytes(tempFile); } return null; } /** * @return 获得文件流 * @throws IOException IO异常 */ public InputStream getFileInputStream() throws IOException { assertValid(); if (data != null) { return IoUtil.toBuffered(IoUtil.toStream(this.data)); } if (tempFile != null) { return IoUtil.toBuffered(IoUtil.toStream(this.tempFile)); } return null; } // ---------------------------------------------------------------- header /** * @return 上传文件头部信息 */ public UploadFileHeader getHeader() { return header; } /** * @return 文件名 */ public String getFileName() { return header == null ? null : header.getFileName(); } // ---------------------------------------------------------------- properties /** * @return 上传文件的大小,> 0 表示未上传 */ public long size() { return size; } /** * @return 是否上传成功 */ public boolean isUploaded() { return size > 0; } /** * @return 文件是否在内存中 */ public boolean isInMemory() { return data != null; } // ---------------------------------------------------------------- process /** * 处理上传表单流,提取出文件 * * @param input 上传表单的流 * @return 是否成功 * @throws IOException IO异常 */ protected boolean processStream(final MultipartRequestInputStream input) throws IOException { if (!isAllowedExtension()) { // 非允许的扩展名 size = input.skipToBoundary(); return false; } size = 0; // 处理内存文件 final int memoryThreshold = setting.memoryThreshold; if (memoryThreshold > 0) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(memoryThreshold); final long written = input.copy(baos, memoryThreshold); data = baos.toByteArray(); if (written <= memoryThreshold) { // 文件存放于内存 size = data.length; return true; } } // 处理硬盘文件 tempFile = FileUtil.createTempFile(TMP_FILE_PREFIX, TMP_FILE_SUFFIX, FileUtil.touch(setting.tmpUploadPath), false); final BufferedOutputStream out = FileUtil.getOutputStream(this.tempFile); if (data != null) { size = data.length; out.write(data); data = null; // not needed anymore } final long maxFileSize = setting.maxFileSize; try { if (maxFileSize == -1) { size += input.copy(out); return true; } size += input.copy(out, maxFileSize - size + 1); // one more byte to detect larger files if (size > maxFileSize) { // 超出上传大小限制 //noinspection ResultOfMethodCallIgnored tempFile.delete(); tempFile = null; input.skipToBoundary(); return false; } } finally { IoUtil.closeQuietly(out); } return true; } // ---------------------------------------------------------------------------- Private method start /** * @return 是否为允许的扩展名 */ private boolean isAllowedExtension() { final String[] exts = setting.fileExts; final boolean isAllow = setting.isAllowFileExts; if (exts == null || exts.length == 0) { // 如果给定扩展名列表为空,当允许扩展名时全部允许,否则全部禁止 return isAllow; } final String fileNameExt = FileNameUtil.extName(this.getFileName()); for (final String fileExtension : setting.fileExts) { if (fileNameExt.equalsIgnoreCase(fileExtension)) { return isAllow; } } // 未匹配到扩展名,如果为允许列表,返回false, 否则true return !isAllow; } /** * 断言是否文件流可用 * * @throws IOException IO异常 */ private void assertValid() throws IOException { if (!isUploaded()) { throw new IOException(StrUtil.format("File [{}] upload fail", getFileName())); } } // ---------------------------------------------------------------------------- Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy