目錄
1、使用場景
我們經常會在開發之中遇見要求上傳文件,特別是後端接口開發過程之中。比如有一下場景:
(1)、我們每個人都需要上傳頭像
(2)、軟件App或者PC端需要針對問題反饋需要上傳兩張反饋截圖
(3)、還有相關論壇或者問題可能需要上傳圖片等操作。
以前我們項目之中主要都是通過 Ftp方式上傳問題圖片,使用封裝的Java後端代碼;但是我們可能實際開發之中可能就要求直接使用Http上傳文件圖片。並且我是遇到一個場景,我們原來業務系統使用的Ftp上傳的文件;結果在部署服務器不開放對應端口;於是要求使用Http上傳文件圖片。最後因爲工期比較緊張;此功能暫時屏蔽啦。於是本文在以前發生的親身經歷需要使用Http方式上傳問題內容。
2、代碼實現
2.1、引入pom.xml jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
2.2、實現代碼
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
/**
* @Classname RequestGetFileInputStream
* @Description 針對上傳文件的相關操作 使用http request方式
* @Date 2019/11/8 18:29
* @Created by jianxiapc
*/
public class UploadFileCommonUtil {
private static Logger logger = LoggerFactory.getLogger(UploadFileCommonUtil.class);
/**
* 通過request之中獲得file的Parts 實現文件的 上傳
* @param request
* @param response
* @param uploadFileDirPath
* @param frontEndFileInputName
* @param renameFileName
* @throws IOException
* @throws ServletException
*/
public static String uploadFileByPartsHttpServletRequest(HttpServletRequest request, HttpServletResponse response,
String uploadFileDirPath, String frontEndFileInputName,String renameFileName) throws IOException, ServletException {
logger.info("request.getContentType(): " + request.getContentType());
if (!request.getContentType().split(";")[0].equals("multipart/form-data")){
return null;
}
Collection<Part> parts = request.getParts();
/**
for(Part part:parts){
System.out.println(part);
String uploadFileDirPath="";
}
*/
String uploadFileWholeDirPath="";
for (Iterator<Part> iterator = parts.iterator(); iterator.hasNext(); ) {
Part part = iterator.next();
logger.info("-----類型名稱------->" + part.getName());
logger.info("-----類型------->" + part.getContentType());
logger.info("-----提交的類型名稱------->" + part.getSubmittedFileName());
logger.info("----流-------->" + part.getInputStream());
uploadFileWholeDirPath= uploadFileProcess(part, uploadFileDirPath, frontEndFileInputName,renameFileName);
}
return uploadFileWholeDirPath;
}
/**
* 通過MultipartHttpServletRequest 實現文件的上傳
* @param request
* @param response
* @param uploadFileDirPath
* @param frontEndFileInputName
* @param renameFileName
* @return
* @throws IOException
*/
public static String uploadFileByMultipartHttpServletRequest(HttpServletRequest request, HttpServletResponse response,
String uploadFileDirPath, String frontEndFileInputName,String renameFileName) throws IOException {
//將當前上下文初始化給 CommonsMutipartResolver (多部分解析器)
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
String uploadFileWholeDirPath="";
// 判斷是否是多數據段提交格式
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iter = multiRequest.getFileNames();
logger.info("iter.hasNext(): " + iter.hasNext());
Integer fileCount = 0;
//文件流
FileOutputStream fileOutputStream = null;
while (iter.hasNext()) {
MultipartFile multipartFile = multiRequest.getFile(iter.next());
String fileName = multipartFile.getOriginalFilename();
logger.info("upload filename: " + fileName);
if (fileName == null || fileName.trim().equals("")) {
continue;
}
//20170207 針對IE環境下filename是整個文件路徑的情況而做以下處理
Integer index = fileName.lastIndexOf("\\");
String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
String newStr = "";
if (index > -1) {
newStr = fileName.substring(index + 1);
} else {
newStr = fileName;
}
if (!newStr.equals("")) {
fileName = newStr;
}
logger.info("new filename: " + fileName);
if (multipartFile != null) {
if(null!=renameFileName&&!"".equals(renameFileName)){
uploadFileWholeDirPath=uploadFileDirPath+renameFileName+ext;
}else{
uploadFileWholeDirPath=uploadFileDirPath+fileName;
}
File storageFile = new File(uploadFileWholeDirPath);
if(!storageFile.getParentFile().exists()){
storageFile.getParentFile().mkdirs();
}
//獲取輸出流
OutputStream os=new FileOutputStream(uploadFileWholeDirPath);
//獲取輸入流 CommonsMultipartFile 中可以直接得到文件的流
InputStream is=multipartFile.getInputStream();
int temp;
//一個一個字節的讀取並寫入
while((temp=is.read())!=(-1))
{
os.write(temp);
}
os.flush();
os.close();
is.close();
}
}
}
return uploadFileWholeDirPath;
}
/**
* 上傳文件的處理函數
* @param part
* @param uploadFileDirPath
* @param frontEndFileInputName
* @param renameFileName 是否需要重新命名文件名稱
* @return
* @throws IOException
*/
private static String uploadFileProcess(Part part, String uploadFileDirPath, String frontEndFileInputName,String renameFileName) throws IOException {
String uploadFileWholeDirPath="";
if (part.getName().equals(frontEndFileInputName)) {
String cd = part.getHeader("Content-Disposition");
String[] cds = cd.split(";");
String filename = cds[2].substring(cds[2].indexOf("=") + 1).substring(cds[2].lastIndexOf("//") + 1).replace("\"", "");
String ext = filename.substring(filename.lastIndexOf(".") + 1);
logger.info("filename:" + filename);
logger.info("ext:" + ext);
InputStream is = part.getInputStream();
if (Arrays.binarySearch(ImageIO.getReaderFormatNames(), ext) >= 0)
uploadImageProcess(uploadFileDirPath, filename, ext, is);
else {
uploadCommonFileProcess(uploadFileDirPath, filename, is);
}
if(null!=renameFileName&&!"".equals(renameFileName)){
uploadFileWholeDirPath=uploadFileDirPath+renameFileName+ext;
}else{
uploadFileWholeDirPath=uploadFileDirPath+filename;
}
}
return uploadFileWholeDirPath;
}
/**
* 通用文件上傳處理
*
* @param uploadFileDirPath
* @param filename
* @param is
*/
private static void uploadCommonFileProcess(String uploadFileDirPath, String filename, InputStream is) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(uploadFileDirPath + filename));
int b = 0;
while ((b = is.read()) != -1) {
fos.write(b);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 圖片文件上傳處理
*
* @param uploadFileDirPath
* @param filename
* @param ext
* @param is
* @throws IOException
*/
public static void uploadImageProcess(String uploadFileDirPath, String filename, String ext, InputStream is) throws IOException {
Iterator<ImageReader> irs = ImageIO.getImageReadersByFormatName(ext);
ImageReader ir = irs.hasNext() ? irs.next() : null;
if (ir == null)
return;
//必須轉換爲ImageInputStream,否則異常
ir.setInput(ImageIO.createImageInputStream(is));
ImageReadParam rp = ir.getDefaultReadParam();
Rectangle rect = new Rectangle(0, 0, 200, 200);
rp.setSourceRegion(rect);
//allowSearch必須爲true,否則有些圖片格式imageNum爲-1。
int imageNum = ir.getNumImages(true);
logger.info("imageNum:" + imageNum);
for (int imageIndex = 0; imageIndex < imageNum; imageIndex++) {
BufferedImage bi = ir.read(imageIndex, rp);
ImageIO.write(bi, ext, new File(uploadFileDirPath + filename));
}
}
}
import org.spring.springboot.excel.poi.export.utils.annotation.FileStorageProperties;
import org.spring.springboot.excel.poi.export.utils.common.UploadFileCommonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Classname UploadFileController
* @Description 基本的文件上傳實現測試
* @Date 2019/11/9 11:42
* @Created by jianxiapc
*/
@RestController
public class UploadFileController {
@Autowired
private FileStorageProperties fileStorageProperties;
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String uploadFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("importExelFile") MultipartFile file) throws Exception {
String uploadFileDirPath =fileStorageProperties.getUploadDir();
//String storageFilePath=UploadFileCommonUtil.uploadFileByPartsHttpServletRequest(request,response,uploadFileDirPath,"importExelFile",null);
String storageFilePath=UploadFileCommonUtil.uploadFileByMultipartHttpServletRequest(request,response,uploadFileDirPath,"importExelFile",null);
return storageFilePath;
}
}
3、成果展現
4、總結
通過本文章可以實現了基本文件通過HttpRequest方式上傳文件的實現。
本人源碼所在地址: 源碼地址:https://github.com/jianxia612/springboot-excel-import-export-fileupload.git