当前位置: 首页 > news >正文

哈尔滨制作手机网站如何让百度快速收录新网站

哈尔滨制作手机网站,如何让百度快速收录新网站,居众装饰,网站技术维护文章目录 1 前言2 Maven 依赖3 上传接口4 如何解析 MultipartFormDataInput5 结语 1 前言 使用 Spring MVC 来处理文件上传,想必是大家耳熟能详的了,如下代码: ResponseBody PostMapping("/upload") public String upload(Request…

文章目录

  • 1 前言
  • 2 Maven 依赖
  • 3 上传接口
  • 4 如何解析 MultipartFormDataInput
  • 5 结语

1 前言

  使用 Spring MVC 来处理文件上传,想必是大家耳熟能详的了,如下代码:

@ResponseBody
@PostMapping("/upload")
public String upload(@RequestPart("file") MultipartFile file) throws IOException {appService.upload(file);return "Success";
}

  😜 但是现在,如果我们不使用 Spring MVC , 而是使用 javax.ws.rs 下的注解,该如何实现文件上传呢?

2 Maven 依赖

<properties><jboss.resteasy.version>3.6.3.Final</jboss.resteasy.version>
</properties><dependencies><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-client</artifactId><version>${jboss.resteasy.version}</version></dependency><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-jackson2-provider</artifactId><version>${jboss.resteasy.version}</version></dependency><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-jaxb-provider</artifactId><version>${jboss.resteasy.version}</version></dependency><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-jaxrs</artifactId><version>${jboss.resteasy.version}</version></dependency><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-netty</artifactId><version>${jboss.resteasy.version}</version></dependency><!-- resteasy 文件上传的依赖开始 --><dependency><groupId>org.jboss.resteasy</groupId><artifactId>resteasy-multipart-provider</artifactId><version>${jboss.resteasy.version}</version></dependency><!-- resteasy 文件上传的依赖结束 -->
</dependencies>

3 上传接口

import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;@Path("/test")
public interface TestController {@POST@Path("upload")@Produces(MediaType.APPLICATION_JSON)@Consumes(MediaType.MULTIPART_FORM_DATA)JsonResult<String> upload(MultipartFormDataInput input);
}

4 如何解析 MultipartFormDataInput

  从 MultipartFormDataInput 中应当可以解析出文件 或者其他 form-data 的字段。通过下面的 getDtoFromMultipartFormDataInput() 方法,我们就可以把多部件转换为指定类型的 dto 了。然后就可以进行 DAO 层操作了。

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;import javax.ws.rs.core.MultivaluedMap;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;@Slf4j
public class TestService {/*** multipart-form/data 的文件的 key 统一为 file*/private static final String FORM_FILE_KEY = "file";/*** 把 {@link MultipartFormDataInput} 转换为指定类型的 dto** @param input 多部件上传的参数, 里面可能有文件, 也可能只是普通的 key-value* @param clazz dto 的类型* @return dto*/public <T> T getDtoFromMultipartFormDataInput(MultipartFormDataInput input, Class<? extends T> clazz) {T dto;try {dto = clazz.newInstance();} catch (InstantiationException | IllegalAccessException e) {log.error("[把多部件转换为 dto] 无法实例化 dto, 类名: {}", clazz.getName());throw new RuntimeException("[把多部件转换为 dto] 无法实例化 dto, 类名: " + clazz.getName(), e);}Map<String, List<InputPart>> formDataMap = input.getFormDataMap();// 处理多部件中的文件, 可能需要解析文件, 也可能不需要, 全看 dto 里面有没有 file 字段this.handleFileFieldIfNeed(clazz, formDataMap, dto);// 解析 multipart/form-data 的其他字段this.handleNonFileFields(clazz, formDataMap, dto);return dto;}/*** 处理 dto 中 非文件类型的字段** @param clazz       dto 的类型* @param formDataMap 多部件的内容* @param dto         dto 实例, new 出来的* @param <T>         泛型, dto 的类型*/private <T> void handleNonFileFields(Class<? extends T> clazz, Map<String, List<InputPart>> formDataMap, T dto) {Field[] dtoFields = clazz.getDeclaredFields();for (Field dtoField : dtoFields) {String fieldName = dtoField.getName();if (!"file".equals(fieldName)) {// 处理非文件的字段List<InputPart> inputParts = formDataMap.get(fieldName);if (CollectionUtils.isEmpty(inputParts)) {log.warn("[把多部件转换为 dto] dto 里面不存在 multipart/form-data 中的字段: {}", fieldName);} else {// 只取第一个InputPart inputPart = inputParts.get(0);try {Object dtoFieldValue = inputPart.getBody(dtoField.getType(), null);boolean accessible = dtoField.isAccessible();if (!accessible) {dtoField.setAccessible(true);}dtoField.set(dto, dtoFieldValue);if (!accessible) {dtoField.setAccessible(false);}} catch (IOException | IllegalAccessException e) {log.error("[把多部件转换为 dto] dto 字段: " + fieldName + " 无法从 form-data 中获取值", e);throw new RuntimeException("[把多部件转换为 dto] dto 字段: " + fieldName + " 无法从 form-data 中获取值", e);}}}}}/*** 处理多部件中的文件, 可能需要解析文件, 也可能不需要, 全看 dto 里面有没有 file 字段** @param clazz       dto 的类型* @param formDataMap 多部件的内容* @param dto         dto 实例, new 出来的* @param <T>         泛型, dto 的类型*/private <T> void handleFileFieldIfNeed(Class<? extends T> clazz, Map<String, List<InputPart>> formDataMap, T dto) {try {Field fileField = clazz.getDeclaredField("file");if (File.class.equals(fileField.getType())) {// 如果 dto 里面有 file 这个字段, 而且 file 字段的类型是 java.io.File, 那么就开始解析// multipart/form-data 的内容, 解析出一个文件出来List<InputPart> inputParts = formDataMap.get(FORM_FILE_KEY);if (CollectionUtils.isEmpty(inputParts)) {throw new RuntimeException("[把多部件转换为 dto] 上传文件的 form-data 的 key 应该为 file");}// 一个 key "file", 只对应一个 文件InputPart inputPart = inputParts.get(0);// 解析文件名MultivaluedMap<String, String> headers = inputPart.getHeaders();String filename = this.getFilename(headers).orElseThrow(() -> new RuntimeException("[把多部件转换为 dto] 解析文件名称失败"));// 解析文件流try (InputStream is = inputPart.getBody(InputStream.class, null)) {// 先生成本地的临时文件File file = this.stream2file(is, filename);// 然后把这个文件设置到 dto 的 file 字段里面boolean fileFieldAccessible = fileField.isAccessible();if (!fileFieldAccessible) {fileField.setAccessible(true);}fileField.set(dto, file);if (!fileFieldAccessible) {fileField.setAccessible(false);}} catch (IOException e) {log.error("[把多部件转换为 dto] 获取文件输入流 或者把此输入流转换为字节数组失败", e);throw new RuntimeException("[把多部件转换为 dto] 获取文件输入流 或者把此输入流转换为字节数组失败");} catch (IllegalAccessException e) {log.error("[把多部件转换为 dto] 把 File 设置到 dto 的 file 字段时, 失败", e);throw new RuntimeException("[把多部件转换为 dto] 把 File 设置到 dto 的 file 字段时, 失败");}}} catch (NoSuchFieldException e) {// 没有名称为 file 的字段log.warn("[把多部件转换为 dto] dto 里面没有 file 字段. class:{}", clazz.getName());}}/*** 从 http 请求头中, 获取文件的名称** @param headers http 请求头* @return 文件的名称, 可能为空*/private Optional<String> getFilename(MultivaluedMap<String, String> headers) {String[] contentDispositionArr = headers.getFirst("Content-Disposition").split(";");for (String contentDisposition : contentDispositionArr) {if (contentDisposition.trim().startsWith("filename")) {String[] filenameArr = contentDisposition.split("=");String filename = filenameArr[1].trim().replaceAll("\"", "");if (!StringUtils.hasText(filename)) {// 文件名为空的话, 也是不可以的return Optional.empty();}String finalFilename = this.urlDecodeFilename(filename);return Optional.ofNullable(finalFilename);}}return Optional.empty();}/*** 把字节输入流 转换为 临时文件.* 这些临时文件要记得及时清除** @param is       字节输入流* @param filename 文件名* @return 临时文件*/private File stream2file(InputStream is, String filename) {File file = this.createTempFile(filename);try (FileOutputStream fos = new FileOutputStream(file)) {IOUtils.copy(is, fos);} catch (IOException e) {log.error("把输入流的内容拷贝到文件输出流 失败", e);}return file;}/*** 创建临时文件** @param filename 临时文件名, 不包含路径* @return 临时文件*/public File createTempFile(String filename) {// 统一的临时文件上传目录. 目录加了日期和uuid的区分String tmpParentDirPath = this.getTmpFileParentDirPath()+ File.separator;File file = new File(tmpParentDirPath + filename);File parentDir = file.getParentFile();if (!parentDir.exists()) {// 生成父目录//noinspection ResultOfMethodCallIgnoredparentDir.mkdirs();}if (!file.exists()) {try {//noinspection ResultOfMethodCallIgnoredfile.createNewFile();} catch (IOException e) {log.error("创建临时文件失败, 文件名: {}", file.getAbsolutePath());throw new RuntimeException("创建临时文件失败, 文件名: " + file.getAbsolutePath(), e);}}return file;}/*** 获取临时文件所在的父目录*/private String getTmpFileParentDirPath() {// 父目录的格式是 D:/年月日/uuidreturn "D:" + File.separator+ DateTimeUtil.formatString(new Date(), "yyyy-MM-dd")+ File.separator+ UUID.randomUUID().toString().replaceAll("-", "");}
}

  这个 dto 可以是:

import java.io.File;@Data
public class MyTestDto {private File file;private String queryParamOne;private String queryParamTwo;
}

5 结语

  感谢阅读~

http://www.tj-hxxt.cn/news/83611.html

相关文章:

  • 国内全屏网站有哪些seo关键词软件
  • 专门做正品的网站手机版武汉seo技术
  • 网站建设资质什么软件可以找客户资源
  • 短视频运营公司网站建设网络营销与直播电商是干什么的
  • 资讯类网站建设资质要求广州市疫情最新
  • 自适应网站案例源码seo推广官网
  • 站长之家字体广州新闻报道
  • 合肥网站设计goz广东深圳龙华区
  • 个人婚礼网站设计域名注册哪个平台比较好
  • 在中国做外国网站怎么收钱广告联盟官网入口
  • 天津滨海新区旅游景点seo是什么岗位简称
  • 网站建设开发费怎么做账百度信息流推广
  • 建设沙滩车官方网站网络推广宣传
  • 网站漂浮广告代码企业宣传册模板
  • 自助微信网站设计seo求职
  • 做前端网站用什么软件写代码怎么建网站卖东西
  • php彩票网站建设源码网站收录免费咨询
  • 便宜点的网站空间网站制作公司怎么样
  • 18款禁用网站app破解版搜索引擎营销的流程
  • 家居企业网站建设公司谷歌搜索引擎免费入口
  • 新网网站空间独立控制面板郑州网站关键词优化外包
  • 同城信息网站建设广州seo顾问服务
  • 佛山网站开发seo数据是什么
  • 做网站的人属于什么行业怎样才能在百度上面做广告宣传
  • 政府网站建设方案范文 工作方案东莞seo优化团队
  • 企业建设网站的必要性百度收录网站入口
  • 太仓做网站的代运营公司
  • 优质的网站2020做seo还有出路吗
  • 做网站开发需要什么seo全网营销
  • 重庆百度关键词推广seo sem